// ---------------------------------------------------------------------------------------------------------------------
//!                                                       Imports
// ---------------------------------------------------------------------------------------------------------------------

// ------------------------------------------------------ React --------------------------------------------------------
import { MouseEvent, useCallback, useState } from 'react';
// ---------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------- Context -------------------------------------------------------
import { useRecoilState } from 'recoil';
import { gameStateAtom } from '../../contexts/gameState';
// ---------------------------------------------------------------------------------------------------------------------

// ------------------------------------------------------ Utils --------------------------------------------------------
import { Difficulty } from '../../types/game';
import { discoverAroundCell, genGrid, revealAllGrid, startGame } from '../../utils/game';
// ---------------------------------------------------------------------------------------------------------------------

// ----------------------------------------------------- Assets --------------------------------------------------------
import Bomb from '../../assets/bomb.png';
import Flag from '../../assets/flag.png';
import './styles.scss';
import Podium from '../../assets/podium';
// ---------------------------------------------------------------------------------------------------------------------

const Grid = () => {
	const [gameState, setGameState] = useRecoilState(gameStateAtom);

	const [grid, setGrid] = useState(genGrid(gameState.gridSize));

	const [, updateGrid] = useState({});
	const forceUpdate = useCallback(() => updateGrid({}), []);

	// ----------------------------------------------------- Actions -------------------------------------------------------
	const handleLeftClick = (ev: MouseEvent, rowIndex: number, colIndex: number) => {
		ev.preventDefault();

		if (grid[rowIndex][colIndex].hidden && !grid[rowIndex][colIndex].flag) {
			setGrid((prev) => {
				if (gameState.status === 'idle') {
					const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, true, rowIndex, colIndex);
					prev = newGrid;

					setGameState((prevGameState) => ({
						...prevGameState,
						status: 'playing',
						bombs: bombsCount,
					}));
				}

				if (prev[rowIndex][colIndex].value === 'bomb') {
					setGameState((prev) => ({
						...prev,
						endType: 'loose',
					}));
					return revealAllGrid(grid, true);
				}

				return discoverAroundCell(prev, rowIndex, colIndex);
			});
			forceUpdate();
		}
	};

	const handleRightClick = (ev: MouseEvent, rowIndex: number, colIndex: number) => {
		ev.preventDefault();

		if (grid[rowIndex][colIndex].hidden) {
			setGrid((prev) => {
				if (gameState.status === 'idle') {
					const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, false);
					prev = newGrid;

					setGameState((prevGameState) => ({
						...prevGameState,
						status: 'playing',
						bombs: bombsCount,
					}));
				}

				return prev.map((row, idx) => {
					if (idx === rowIndex) {
						return row.map((col, idy) => {
							if (idy === colIndex) {
								setGameState((prevGameState) => ({
									...prevGameState,
									placedFlags: col.flag ? prevGameState.placedFlags - 1 : prevGameState.placedFlags + 1,
								}));

								return {
									...col,
									flag: !col.flag,
								};
							}
							return col;
						});
					}
					return row;
				});
			});
		}
	};
	// ---------------------------------------------------------------------------------------------------------------------

	return (
		<div
			className='grid'
			style={{
				gridTemplateRows: `repeat(${gameState.gridSize}, var(--size))`,
			}}
		>
			{grid.map((row, rowIndex) => (
				<div
					key={`row${rowIndex}`}
					className='row'
					style={{
						gridTemplateColumns: `repeat(${gameState.gridSize}, var(--size))`,
					}}
				>
					{row.map((cell, cellIndex) => {
						return (
							<button
								key={`cell${cellIndex}`}
								className={`cell ${cell.hidden ? 'hidden' : cell.value !== 'empty' ? `v${cell.value}` : ''}`}
								onClick={(ev) => handleLeftClick(ev, rowIndex, cellIndex)}
								onContextMenu={(ev) => handleRightClick(ev, rowIndex, cellIndex)}
							>
								{cell.hidden && cell.flag && (
									<img
										src={Flag}
										alt='flat'
									/>
								)}
								{!cell.hidden &&
									(cell.value === 'bomb' ? (
										<img
											src={Bomb}
											alt='bomb'
										/>
									) : cell.value !== 'empty' ? (
										cell.value
									) : (
										''
									))}
							</button>
						);
					})}
				</div>
			))}
			{gameState.endType !== '' && (
				<div
					className='overlay'
					style={
						{
							'--overlayColor': gameState.endType === 'win' ? '#5f8e59' : '#ca5940',
						} as React.CSSProperties
					}
				>
					<p className='overlayTitle'>{gameState.endType === 'win' ? 'Gagné !' : 'Perdu !'}</p>
					<button
						className='overlayButton'
						onClick={() => setGameState((prev) => ({ ...prev, status: 'board' }))}
					>
						<Podium />
						Leaderboard
					</button>
				</div>
			)}
		</div>
	);
};

export default Grid;
