package Server;

import Server.Cards.BuildingCard;

import Server.Cards.CardDeck;
import Server.Cards.CharacterCard;
import Server.Cards.EventCard;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.List;

class BuildingManagerTest {

    static List<Player> players = new ArrayList<>();

    @BeforeAll
    static void setUp(){
        BuildingManager buildingManager = new BuildingManager();

        Player winner = new Player("Winner", TotemColor.YELLOW);
        winner.addFood(10);
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;1;2;I;SHAMAN;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;2;2;I;SHAMAN;2;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;3;2;I;BUILDER;3;1"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;12;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;13;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;12;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;13;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;12;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;13;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;12;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;13;3;I;GATHERER;3;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;14;0;I;ARTIST;0;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;15;0;I;ARTIST;0;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;21;0;I;ARTIST;1;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;22;0;I;INVENTOR;9;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;23;4;I;INVENTOR;5;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;43;0;I;HUNTER;0;0"));
        winner.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;44;3;I;HUNTER;0;0"));
        players.add(winner);

        Player medium = new Player("Medium", TotemColor.RED);
        medium.addFood(10);
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;56;2;I;SHAMAN;3;0"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;34;2;I;BUILDER;3;1"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;32;3;I;GATHERER;3;0"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;33;0;I;ARTIST;0;0"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;45;3;I;HUNTER;0;0"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;72;0;I;ARTIST;9;0"));
        medium.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;73;4;I;INVENTOR;5;0"));
        players.add(medium);

        Player loser = new Player("Loser", TotemColor.BLUE);
        loser.addFood(2);
        loser.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;54;2;I;SHAMAN;3;0"));
        loser.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;36;2;I;BUILDER;3;1"));
        loser.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;82;0;I;INVENTOR;9;0"));
        loser.getPlayerTribe().addCharacter(CharacterCard.parsRow("C;93;4;I;INVENTOR;5;0"));
        players.add(loser);

        CardDeck cardDeck = new CardDeck();
        //cardDeck.setForNPlayerPath("./src/test/resources/files/only_building_deck.csv", 5);
        cardDeck.setForNPlayer(BuildingManagerTest.class.getResourceAsStream("/files/only_building_deck.csv"), 4);
        //for(BuildingCard c: cardDeck.drawBuilding(30)){
        //    buildingManager.addActiveBuilding(c, players.getFirst());
        //}
        //buildingManager.addActiveBuilding(BuildingCard.parsRow("B;5;3;III;6;2;SHAMAN_NO_LOSS"), players.get(2));
    }

    @Test
    void foodForSix() {
        int initialFood = players.getFirst().getFoodTokens();
        CharacterCard cardForSix = CharacterCard.parsRow("C;39;2;I;BUILDER;3;1");
        BuildingManager.foodForSix(players.getFirst(), cardForSix);
        assertEquals(initialFood + 6, players.getFirst().getFoodTokens());

        players.getFirst().getPlayerTribe().addCharacter(cardForSix);
        BuildingManager.foodForSix(players.getFirst(), cardForSix);
        assertEquals(initialFood + 6, players.getFirst().getFoodTokens());
    }

    @Test
    void sustainDiscount() {

        EventCard sustainment = EventCard.parsRow("E;1;0;I;SUSTAINMENT;2;0");
        ArrayList<Integer> target = new ArrayList<>();
        target.add(players.getFirst().getFoodTokens());
        target.add(players.getFirst().getPrestigePoints());
        target.add(players.get(1).getFoodTokens() - 4);
        target.add(players.get(1).getPrestigePoints());
        target.add(0);
        target.add(players.get(2).getPrestigePoints()-4);
        assertEquals(target, EventsSolver.sustainment(sustainment, players));
    }

    @Test
    void shamanicBuildings() {
        EventCard shamanicRitual =  EventCard.parsRow("E;1;0;I;SHAMANIC_RITUAL;10;5");
        ArrayList<Integer> target = new ArrayList<>();
        target.add(players.getFirst().getPrestigePoints() + 20);
        target.add(players.get(1).getPrestigePoints()-5);
        target.add(players.get(2).getPrestigePoints());
        assertEquals(target, EventsSolver.shamanicRitual(shamanicRitual, players));
    }

    @Test
    void bonusEndTurn() {
        assertEquals(1, BuildingManager.bonusEndTurn(players.getFirst(), 1));
        assertEquals(0, BuildingManager.bonusEndTurn(players.getFirst(), 0));
        assertEquals(0, BuildingManager.bonusEndTurn(players.getFirst(), -1));
    }

    @Test
    void foodPerInventors() {
        int initialFood = players.getFirst().getFoodTokens();
        CharacterCard builder = CharacterCard.parsRow("C;57;2;I;INVENTOR;9;0");
        BuildingManager.foodPerInventors(players.getFirst(), builder);
        assertEquals(initialFood + 3, players.getFirst().getFoodTokens());

        players.getFirst().getPlayerTribe().addCharacter(builder);
        BuildingManager.foodPerInventors(players.getFirst(), builder);
        assertEquals(initialFood+3, players.getFirst().getFoodTokens());

        initialFood = players.get(2).getFoodTokens();
        BuildingManager.foodPerInventors(players.get(2), builder);
        assertEquals(initialFood, players.get(2).getFoodTokens());
    }

    @Test
    void shamanBonus() {
        assertEquals(3, BuildingManager.shamanBonus(players.getFirst()));
        assertEquals(0, BuildingManager.shamanBonus(players.get(1)));
    }

    @Test
    void hunterBonus() {
        EventCard hunt = EventCard.parsRow("E;1;0;I;HUNT;2;0");
        ArrayList<Integer> target = new ArrayList<>();
        target.add(players.getFirst().getFoodTokens()+4);
        target.add(players.getFirst().getPrestigePoints()+6);
        target.add(players.get(1).getFoodTokens()+1);
        target.add(players.get(1).getPrestigePoints()+2);
        target.add(players.get(2).getFoodTokens());
        target.add(players.get(2).getPrestigePoints());
        assertEquals(target, EventsSolver.hunt(hunt, players));
    }

    @Test
    void endgameBuilderBonus() {
    }

    @Test
    void paintingFoodBonus() {
        int winnerInitial = players.getFirst().getFoodTokens();
        int middleInitial = players.get(1).getFoodTokens();

        EventCard cavePainting = EventCard.parsRow("E;4;4;FINAL;CAVE_PAINTINGS;2;2");
        EventsSolver.cavePaintings(cavePainting, players);
        assertEquals(winnerInitial + 3 , players.getFirst().getFoodTokens());
        assertEquals(middleInitial, players.get(1).getFoodTokens());
    }

    @Test
    void endgameForSix() {
        int winnerInitial = players.getFirst().getPrestigePoints();
        int middleInitial = players.get(1).getPrestigePoints();

        BuildingManager.endgameForSix(players.getFirst());
        BuildingManager.endgameForSix(players.get(1));
        assertEquals(winnerInitial + 6 , players.getFirst().getPrestigePoints());
        assertEquals(middleInitial, players.get(1).getPrestigePoints());
    }

    @Test
    void endgameBonusCharacter() {
        int winnerInitial = players.getFirst().getPrestigePoints();
        int middleInitial = players.get(1).getPrestigePoints();

        BuildingManager.endgameBonusCharacter(players.getFirst());
        BuildingManager.endgameBonusCharacter(players.get(1));
        assertEquals(winnerInitial + 9 , players.getFirst().getPrestigePoints());
        assertEquals(middleInitial, players.get(1).getPrestigePoints());
    }

    @Test
    void extraDraw() {
        assertTrue(BuildingManager.extraDraw(players.getFirst()));
        assertFalse(BuildingManager.extraDraw(players.get(1)));
    }

    @Test
    void endgameBonusPoints() {
        int initialWinner = players.getFirst().getPrestigePoints();
        int initialMedium = players.get(1).getPrestigePoints();

        BuildingManager.endgameBonusPoints(players.getFirst());
        BuildingManager.endgameBonusPoints(players.get(1));
        assertEquals(initialWinner+25, players.getFirst().getPrestigePoints());
        assertEquals(initialMedium, players.get(1).getPrestigePoints());
    }
}