namespace Game
{
    public class ConnectFour
    {
        public long[] bitboards;
        public int[] heights;
        public int counter;
        public List<int> moves;

        public ConnectFour()
        {
            bitboards = [0, 0];
            heights = [0, 7, 14, 21, 28, 35, 42];
            counter = 0;
            moves = [];
        }

        public void Play(int column)
        {
            bitboards[counter & 1] ^= 1 << heights[column];

            moves.Add(column);

            heights[column] += 1;
            counter += 1;
        }

        public void Undo()
        {
            counter -= 1;
            
            int prev = moves.ElementAt(counter);
            moves.RemoveAt(counter);

            heights[prev] -= 1;

            bitboards[counter & 1] ^= 1 << heights[prev];
        }

        public bool HasWon()
        {
            int[] directions = [1, 7, 6, 8];
            long current = bitboards[counter & 1];

            foreach (int direction in directions)
            {
                long bb = current & current >> direction;

                if ((bb & bb >> 2 * direction) != 0)
                {
                    return true;
                }
            }
            
            return false;
        }

        public List<int> NextMoves()
        {
            List<int> moves = new();

            for (int i = 0; i < 7; i++)
            {
                if (heights[i] < 7 * (i + 1) - 1)
                {
                    moves.Add(i);
                }
            }

            return moves;
        }

        public string DisplayBoard()
        {
            List<string> board = [];

            for (int i = 0; i < 6; i++)
            {
                var line = "";

                for (int j = 0; j < 7; j++)
                {
                    long sq = 1 << j * 7 + i;

                    Console.WriteLine($"On square {sq}");

                    if ((bitboards[0] & sq) != 0)
                    {
                        line += "1 ";
                    }
                    else if ((bitboards[1] & sq) != 0)
                    {
                        line += "2 ";
                    }
                    else
                    {
                        line += ". ";
                    }
                }

                board.Add(line);
            }

            board.Reverse();

            return string.Join('\n', board);
        }
    }
}