package it.polimi.ingsw.gc14.Model.GamePackage;

import it.polimi.ingsw.gc14.Model.Cards.BuildingCard;
import it.polimi.ingsw.gc14.Model.Cards.TribeCard;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.EventCard;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.ShamanicRitual;
import it.polimi.ingsw.gc14.Model.Cards.TribeCards.Events.Sustenance;
import it.polimi.ingsw.gc14.Model.DecksCreator;
import it.polimi.ingsw.gc14.Model.OrderLogicCard;
import it.polimi.ingsw.gc14.Model.Orders.Order2;
import it.polimi.ingsw.gc14.Model.Orders.Order3;
import it.polimi.ingsw.gc14.Model.Orders.Order4;
import it.polimi.ingsw.gc14.Model.Orders.Order5;
import it.polimi.ingsw.gc14.Model.Slot;

import java.util.*;
import java.util.stream.Collectors;

public class Board {
    private List<Slot> slotList;
    private Queue<TribeCard> tribeDeck;
    private List<TribeCard> upperListTribe;
    private List<TribeCard> lowerListTribe;
    private List<BuildingCard> upperListBuilding;
    private List<BuildingCard> lowerListBuilding;
    private int nTotem;
    private int era;
    public List<Slot> getSlotList(){
        return slotList.stream().map(x->new Slot(x.getSlotId())).collect(Collectors.toList());
    }

    public Board(int nTotem) {
        this.nTotem = nTotem;
        this.slotList = DecksCreator.loadSlotDeck().stream().filter(x->x.getNMinPlayer()<=nTotem).sorted(Comparator.comparingInt(Slot::getSlotId)).toList();
        upperListTribe=new ArrayList<>();
        lowerListTribe=new ArrayList<>();
        lowerListBuilding=new ArrayList<>();
        tribeDeck=getTribeDeck(nTotem);
        era=1;
        for(int i=0;i<nTotem+1;i++)
        {
            TribeCard tempCard = tribeDeck.remove();
            if(tempCard.IsEventCard())
            {
                upperListTribe.add(tempCard);
                i--;
            }
            else
            {
                lowerListTribe.add(tempCard);
            }
        }
        for(int i=upperListTribe.size();i<nTotem+5;i++)
        {
            TribeCard tempCard = tribeDeck.remove();
            upperListTribe.add(tempCard);
        }

        ArrayList<BuildingCard> buildingDeck = new ArrayList<>(DecksCreator.loadBuildingDeckByEra(1));
        Collections.shuffle(buildingDeck);
        if(nTotem==2)
            upperListBuilding= buildingDeck.subList(0,1);
        else
            upperListBuilding= buildingDeck.subList(0,2);
    }

    private Queue<TribeCard>  getTribeDeck(int nPlayers) {
        ArrayList<TribeCard> era1= DecksCreator.loadTribeDeckByEra(1).stream().filter(x->x.getNMin()<=nPlayers).collect(Collectors.toCollection(ArrayList::new));
        ArrayList<TribeCard> era2= DecksCreator.loadTribeDeckByEra(2).stream().filter(x->x.getNMin()<=nPlayers).collect(Collectors.toCollection(ArrayList::new));
        ArrayList<TribeCard> era3= DecksCreator.loadTribeDeckByEra(3).stream().filter(x->x.getNMin()<=nPlayers).collect(Collectors.toCollection(ArrayList::new));
        Collections.shuffle(era1);
        Collections.shuffle(era2);
        Collections.shuffle(era3);

        Queue<TribeCard> tribeDeck_temp=new LinkedList<>();
        tribeDeck_temp.addAll(era1);
        tribeDeck_temp.addAll(era2);
        tribeDeck_temp.addAll(era3);
        tribeDeck_temp.add(new Sustenance(3,3));
        tribeDeck_temp.add(new ShamanicRitual(3,15,7));
        return tribeDeck_temp;
    }

    public Queue<EventCard> getPendingEvents(){
        return lowerListTribe.stream().filter(TribeCard::IsEventCard).map(x->(EventCard)x).collect(Collectors.toCollection(LinkedList::new));
    }

    public boolean containsUpperTribeCard(TribeCard tribeCard) {
        return  upperListTribe.contains(tribeCard);
    }
    public boolean removeUpperTribeCard(TribeCard tribeCard) {
        return upperListTribe.remove(tribeCard);
    }
    public boolean containsLowerTribeCard(TribeCard tribeCard) {
        return  upperListTribe.contains(tribeCard);
    }
    public boolean removeLowerTribeCard(TribeCard tribeCard) {
        return upperListTribe.remove(tribeCard);
    }
    public boolean containsUpperBuildingCard(BuildingCard buildingCard) {return  upperListTribe.contains(buildingCard);}
    public boolean removeUpperBuildingCard(BuildingCard buildingCard) {
        return upperListTribe.remove(buildingCard);
    }
    public boolean containsLowerBuildingCard(BuildingCard buildingCard) {return  upperListTribe.contains(buildingCard);}
    public boolean removeLowerBuildingCard(BuildingCard buildingCard) {
        return upperListTribe.remove(buildingCard);
    }
    public int nextRound() {
        lowerListTribe.clear();
        lowerListTribe.addAll(upperListTribe);

        for(int i=0;i<nTotem+4;i++)
        {
            TribeCard tempCard = tribeDeck.remove();
            if(tempCard.getEra()!=era)
            {
                nextEra();
            }
            upperListTribe.add(tempCard);
        }
        for(int i=upperListTribe.size();i<nTotem+5;i++)
        {
            TribeCard tempCard = tribeDeck.remove();
            upperListTribe.add(tempCard);
        }


        return era;
    }
    private void nextEra() {
        era=era+1;
        lowerListBuilding.clear();
        lowerListBuilding.addAll(upperListBuilding);
        upperListBuilding.clear();

        List<BuildingCard> buildingCards=DecksCreator.loadBuildingDeckByEra(era);
        Collections.shuffle(buildingCards);
        if(era==2)
        {
            if(nTotem<=3)
            {
                upperListBuilding.addAll(buildingCards.subList(0,2));
            }
            else
            {
                upperListBuilding.addAll( buildingCards.subList(0,3));
            }
        }
        else if(era==3)
        {
            if(nTotem==2)
            {
                upperListBuilding.addAll( buildingCards.subList(0,3));
            }else if(nTotem==5)
            {
                upperListBuilding.addAll( buildingCards.subList(0,5));
            }
            else {
                upperListBuilding.addAll(buildingCards.subList(0,4));
            }
        }
    }
}
