package Server.Cards;

import Server.Automaton.Game;
import Server.Era;
import Server.Utils.LoadingCardsException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;

public class CardDeck {
    private List<Card> tribeDeck;
    private Map<Era, List<Card>> buildingDeck;
    private static final Logger logger = LogManager.getLogger(CardDeck.class);

    public List<Card> getTribeDeck() {
        return tribeDeck;
    }

    public List<Card> getBuildingDeck(Era era) {
        return buildingDeck.get(era);
    }

    public void setForNPlayerPathTest(String path, int n) throws LoadingCardsException {

        List<Card> tribe = new ArrayList<>();
        List<Card> building = new ArrayList<>();

        try {
            List<String> rows = Files.readAllLines(Path.of(path));
            int p=0;
            for (String row : rows) {
                String cleanRow = row.trim();
                String[] fields = cleanRow.split(";");
                logger.info((p++) +  " ROW " +row);
                switch (fields[0]) {
                    case "C":
                        tribe.add(CharacterCard.parsRow(row));
                        break;
                    case "E":
                        tribe.add(EventCard.parsRow(row));
                        break;
                    case "B":
                        building.add(BuildingCard.parsRow(row));
                        break;
                    default:
                        throw new LoadingCardsException("Content not supported");
                }
            }
        } catch (IOException e) {
            logger.error(e);
            throw new LoadingCardsException("file not found");
        }

        building = CardDeck.shuffle(building);

        this.tribeDeck = new ArrayList<>();

        for(Card card : tribe) {
            if (card.getForMinPlayer() <= n)
                this.tribeDeck.add(card);
        }
        this.tribeDeck = CardDeck.shuffle(this.tribeDeck);

        // groups the building cards by era
        this.buildingDeck = building.stream().collect(Collectors.groupingBy(Card::getEra));
    }



    public void setForNPlayer(InputStream csvStream, int n) throws LoadingCardsException {
        List<Card> tribe = new ArrayList<>();
        List<Card> building = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(csvStream))) {
            String row;
            int p = 0;
            while ((row = reader.readLine()) != null) {
                String cleanRow = row.trim();
                String[] fields = cleanRow.split(";");

                logger.info((p++) + " ROW " + row);

                switch (fields[0]) {
                    case "C":
                        tribe.add(CharacterCard.parsRow(row));
                        break;
                    case "E":
                        tribe.add(EventCard.parsRow(row));
                        break;
                    case "B":
                        building.add(BuildingCard.parsRow(row));
                        break;
                    default:
                        throw new LoadingCardsException("Content not supported");
                }
            }

        } catch (IOException e) {
            logger.error(e);
            throw new LoadingCardsException("file not found");
        }

        building = CardDeck.shuffle(building);

        this.tribeDeck = tribe.stream()
                .filter(card -> card.getForMinPlayer() <= n)
                .collect(Collectors.toCollection(ArrayList::new));

        this.tribeDeck = CardDeck.shuffle(this.tribeDeck);
        this.buildingDeck = building.stream().collect(Collectors.groupingBy(Card::getEra));
    }



    public List<Card> drawTribe(int n) {
        List<Card> cards = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if(tribeDeck.isEmpty()) break;
            cards.add(tribeDeck.getFirst());
            tribeDeck.remove(tribeDeck.getFirst());
        }
        return cards;
    }

    public List<Card> drawBuilding(int n, Era era) {
        List<Card> cards = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            if(buildingDeck.isEmpty()) break;
            Card card = buildingDeck.get(era).getFirst();
            cards.add(card);
            buildingDeck.remove(card);
        }
        return cards;
    }


    public static List<Card> shuffle(List<Card> cards) {
        List<Card> shuffled = new ArrayList<>();

        for(Era e: Era.values()) {
            List<Card> cardsToShuffle = new ArrayList<>();
            for(Card card : cards) {
                if(card.getEra() == e){
                    cardsToShuffle.add(card);
                }
            }
            Collections.shuffle(cardsToShuffle);
            shuffled.addAll(cardsToShuffle);
        }

       return shuffled;
    }

    public Card getFirstCardForCover() {
        if(tribeDeck.isEmpty()) return null;
        Card card = tribeDeck.getFirst();
        return card;
    }

    public Card drawTribeOne() {
        if(tribeDeck.isEmpty()) return null;
        Card card = tribeDeck.getFirst();
        tribeDeck.remove(card);
        return card;
    }

    public Card drawBuildingOne(Era era) {
        if(buildingDeck.isEmpty()) return null;
        Card card = buildingDeck.get(era).getFirst();
        buildingDeck.get(era).remove(card);
        return card;
    }
}
