package it.polimi.ingsw.gc14.Model.Cards.Building.Effects;

import it.polimi.ingsw.gc14.Model.Cards.Building.EffectType;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Characters.*;
import it.polimi.ingsw.gc14.Model.Player;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

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

class Building0Test {
    @Test
    @DisplayName("Testing constructor")
    void testConstructor() {

        int era = 1;
        int price = 10;
        int prestigeValue = 5;

        Building0 b0 = new Building0(era, price, prestigeValue);

        // Gli attributi di BuildingCard era, price e prestigeValue vengono testati in BuildingCardTest

        // Attributi di Building0
        assertEquals(EffectType.CARD_SET, b0.getEffectType());
        assertEquals(0, b0.getEffectId());

        // Gli attributi purchased e numSet non possono essere testati singolarmente in quanto non hanno metodi getter
        // Ne viene testato il corretto funzionamento indirettamente attraverso applyEffect.

        // Lo stesso vale per il metodo initialize
    }

    @Test
    @DisplayName("Testing buy method")
    void testBuy() {
        Player p1 = new Player("test1");
        Player p2 = new Player("test2");
        Building0 b0 = new Building0(1,1,1);

        p1.addFood(10);
        p2.addFood(10);

        assertEquals(true, b0.buy(p1));
        assertEquals(false, b0.buy(p1));
        assertEquals(false, b0.buy(p2));
    }

    @Test
    @DisplayName("Testing clone method")
    void testClone() {
        int effectID = 0;
        EffectType effectType = EffectType.CARD_SET;
        int era = 1;
        int price = 1;
        int prestigeValue = 1;
        Building0 b0 = new Building0(era, price,prestigeValue);

        Building0 b1 = (Building0) b0.clone();

        assertEquals(effectID, b1.getEffectId());
        assertEquals(effectType, b1.getEffectType());
        assertEquals(era, b1.getEra());
        assertEquals(price, b1.getPrice());
        assertEquals(prestigeValue, b1.getPrestigeValue());
    }

    @Test
    @DisplayName("Set Obtained After Effect")
    void applyEffect() {
        int Era = 1;
        // Corretta creazione / esecuzione building card
        Building0 b0 = new Building0(1, 1, 1);
        Player p = new Player("test");
        p.addFood(b0.getPrice());
        b0.buy(p);
        b0.applyEffect(p);

        assertEquals(0, p.getFoodValue());
        Artist a = new Artist(Era);
        Builder b = new Builder(Era, 0, 0);
        Gatherer g = new Gatherer(Era);
        Hunter h = new Hunter(Era, true);
        Inventor i = new Inventor(Era, 1);
        Shaman s = new Shaman(Era,1);
        p.artists.add(a);
        p.builders.add(b);
        p.gatherers.add(g);
        p.hunters.add(h);
        p.inventors.add(i);
        p.shamans.add(s);
        b0.applyEffect(p);
        assertEquals(5, p.getFoodValue());
    }

    @Test
    @DisplayName("Set Obtained Before Effect")
    void applyEffect2() {
        int Era = 1;
        Player p = new Player("test");

        assertEquals(0, p.getFoodValue());
        Artist a = new Artist(Era);
        Builder b = new Builder(Era, 0, 0);
        Gatherer g = new Gatherer(Era);
        Hunter h = new Hunter(Era, true);
        Inventor i = new Inventor(Era, 1);
        Shaman s = new Shaman(Era,1);
        p.artists.add(a);
        p.builders.add(b);
        p.gatherers.add(g);
        p.hunters.add(h);
        p.inventors.add(i);
        p.shamans.add(s);
        assertEquals(0, p.getFoodValue());

        // Corretta creazione / esecuzione building card
        Building0 b0 = new Building0(1, 1, 1);
        p.addFood(b0.getPrice());
        b0.buy(p);
        b0.applyEffect(p);
        assertEquals(0, p.getFoodValue());
    }

    @Test
    @DisplayName("Exception Test")
    void applyEffect3() {
        assertThrows(IllegalArgumentException.class, () -> {
            Building0 b0 = new Building0(1, 1, 1);
            Player p = new Player("test");
            b0.applyEffect(p);
        });
    }

    @Test
    @DisplayName("Buying Of Same Card By Two Different Players")
    void applyEffect4() {
        Building0 b0 = new Building0(1, 1, 1);
        Player p1 = new Player("test1");
        Player p2 = new Player("test2");
        p1.addFood(b0.getPrice());
        p2.addFood(b0.getPrice());
        b0.buy(p1);
        assertFalse(b0.buy(p2));
    }




}