using System;

namespace GoFish
{
    using System.Collections.Generic;
    using System.Linq;

    class Program
    {
        /// <summary>
        /// Obiekt typu GameController zarządzający grą.
        /// </summary>
        static GameController gameController;

        /// <summary>
        /// Zagraj w Go Fish!
        /// </summary>
        static void Main(string[] args)
        {
            Console.Write("Podaj imię: ");
            var humanName = Console.ReadLine();

            Console.Write("Podaj liczbę przeciwników sterowanych przez komputer: ");
            int opponentCount;
            while (!int.TryParse(Console.ReadKey().KeyChar.ToString(), out opponentCount)
                || opponentCount < 1 || opponentCount > 4)
            {
                Console.WriteLine("Wpisz wartość od 1 do 4");
            }
            Console.WriteLine($"{Environment.NewLine}Witaj w grze, {humanName}");


            gameController = new GameController("Człowiek",
                     Enumerable.Range(1, opponentCount).Select(i => $"Gracz{i}"));
            Console.WriteLine(gameController.Status);

            while (!gameController.GameOver)
            {
                while (!gameController.GameOver)
                {
                    Console.WriteLine($"Twoje karty:");
                    foreach (var card in gameController.HumanPlayer.Hand
                        .OrderBy(card => card.Suit)
                        .OrderBy(card => card.Value))
                        Console.WriteLine(card);

                    var value = PromptForAValue();

                    var player = PromptForAnOpponent();

                    gameController.NextRound(player, value);

                    Console.WriteLine(gameController.Status);
                }

                Console.WriteLine("Wciśnij Q, aby zakończyć, lub N, by rozpocząć nową grę.");
                if (Console.ReadKey(true).KeyChar.ToString().ToUpper() == "N")
                    gameController.NewGame();
            }
        }

        /// <summary>
        /// Wyświetla użytkownikowi pytanie o wartość jednej z kart, jakie ma w ręku
        /// </summary>
        /// <returns>Wartość karty, o jaką gracz poprosił</returns>
        static Values PromptForAValue()
        {
            var handValues = gameController.HumanPlayer.Hand.Select(card => card.Value).ToList();
            Console.Write("O jakiej wartości kartę chcesz poprosić? ");
            while (true)
            {
                if (Enum.TryParse(typeof(Values), Console.ReadLine(), out var value) &&
                    handValues.Contains((Values)value))
                    return (Values)value;
                else
                    Console.WriteLine("Podaj wartość karty, jaką masz w ręku.");
            }
        }

        /// <summary>
        /// Wyświetla użytkownikowi pytanie o przeciwnika, od którego chce zażądać karty
        /// </summary>
        /// <returns>Przeciwnik, od którego gracz zażądał karty</returns>
        static Player PromptForAnOpponent()
        {
            var opponents = gameController.Opponents.ToList();
            for (int i = 1; i <= opponents.Count(); i++)
                Console.WriteLine($"{i}. {opponents[i - 1]}");
            Console.Write("Kogo chcesz poprosić o kartę? ");
            while (true)
            {
                if (int.TryParse(Console.ReadLine(), out int selection)
                    && selection >= 1 && selection <= opponents.Count())
                    return opponents[selection - 1];
                else
                    Console.Write($"Wpisz liczbę od 1 do {opponents.Count()}: ");
            }
        }
    }
}
