using System;
namespace GoFishTests
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System.Collections.Generic;
    using System.Linq;
    using GoFish;

    [TestClass]
    public class GameStateTests
    {
        [TestMethod]
        public void TestConstructor()
        {
            var computerPlayerNames = new List<string>()
        {
            "Gracz1",
            "Gracz2",
            "Gracz3",
        };
            var gameState = new GameState("Człowiek", computerPlayerNames, new Deck());

            CollectionAssert.AreEqual(
                new List<string> { "Człowiek", "Gracz1", "Gracz2", "Gracz3" },
                gameState.Players.Select(player => player.Name).ToList());

            Assert.AreEqual(5, gameState.HumanPlayer.Hand.Count());
        }


        [TestMethod]
        public void TestRandomPlayer()
        {
            var computerPlayerNames = new List<string>()
        {
            "Gracz1",
            "Gracz2",
            "Gracz3",
        };

            var gameState = new GameState("Człowiek", computerPlayerNames, new Deck());
            Player.Random = new MockRandom() { ValueToReturn = 1 };
            Assert.AreEqual("Gracz2",
                            gameState.RandomPlayer(gameState.Players.ToList()[0]).Name);

            Player.Random = new MockRandom() { ValueToReturn = 0 };
            Assert.AreEqual("Człowiek", gameState.RandomPlayer(gameState.Players.ToList()[1]).Name);
            Assert.AreEqual("Gracz1",
                            gameState.RandomPlayer(gameState.Players.ToList()[0]).Name);
        }

        [TestMethod]
        public void TestPlayRound()
        {
            var deck = new Deck();
            deck.Clear();
            var cardsToAdd = new List<Card>() {

            // Karty rozdawane Oskarowi.
            new Card(Values.Walet, Suits.pik),
            new Card(Values.Walet, Suits.kier),
            new Card(Values.Szóstka, Suits.pik),
            new Card(Values.Walet, Suits.karo),
            new Card(Values.Szóstka, Suits.kier),

            // Karty rozdawane Basi.
            new Card(Values.Szóstka, Suits.karo),
            new Card(Values.Szóstka, Suits.trefl),
            new Card(Values.Siódemka, Suits.pik),
            new Card(Values.Walet, Suits.trefl),
            new Card(Values.Dziewiątka, Suits.pik),

            // Dwie dodatkowe karty z kupki dla Oskara dobierane po wyczerpaniu się kart na ręce.
            new Card(Values.Dama, Suits.kier),
            new Card(Values.Król, Suits.pik),
        };

            foreach (var card in cardsToAdd)
                deck.Add(card);

            var gameState = new GameState("Oskar", new List<string>() { "Basia" }, deck);

            var owen = gameState.HumanPlayer;
            var brittney = gameState.Opponents.First();

            Assert.AreEqual("Oskar", owen.Name);
            Assert.AreEqual(5, owen.Hand.Count());
            Assert.AreEqual("Basia", brittney.Name);
            Assert.AreEqual(5, brittney.Hand.Count());

            var message = gameState.PlayRound(owen, brittney, Values.Walet, deck);
            Assert.AreEqual("Oskar prosi gracza Basia o kartę Walet" + Environment.NewLine +
                "Basia - liczba kart Walet to 1", message);
            Assert.AreEqual(1, owen.Books.Count());
            Assert.AreEqual(2, owen.Hand.Count());
            Assert.AreEqual(0, brittney.Books.Count());
            Assert.AreEqual(4, brittney.Hand.Count());

            message = gameState.PlayRound(brittney, owen, Values.Szóstka, deck);
            Assert.AreEqual("Basia prosi gracza Oskar o kartę Szóstka" + Environment.NewLine +
                "Oskar - liczba kart Szóstka to 2", message);
            Assert.AreEqual(1, owen.Books.Count());
            Assert.AreEqual(2, owen.Hand.Count());
            Assert.AreEqual(1, brittney.Books.Count());
            Assert.AreEqual(2, brittney.Hand.Count());

            message = gameState.PlayRound(owen, brittney, Values.Dama, deck);
            Assert.AreEqual("Oskar prosi gracza Basia o kartę Dama" + Environment.NewLine +
                "Oskar dobrał(a) kartę", message);
            Assert.AreEqual(1, owen.Books.Count());
            Assert.AreEqual(2, owen.Hand.Count());
        }

        [TestMethod]
        public void TestCheckForAWinner()
        {
            var computerPlayerNames = new List<string>()
        {
            "Gracz1",
            "Gracz2",
            "Gracz3",
        };

            var emptyDeck = new Deck();
            emptyDeck.Clear();
            var gameState = new GameState("Człowiek", computerPlayerNames, emptyDeck);
            Assert.AreEqual("Wygrali Człowiek, Gracz1, Gracz2, Gracz3",
                            gameState.CheckForWinner());
        }
    }
}
