#pragma once

#include "../Pieces/Piece.h"
#include "DistributionMode.h"

#include <vector>
#include <utility>


/**
 * A container for all loaded pieces to prevent loading and copying them multiple times,
 * also allows for the player to select a list of pieces to be used in a game
 */
class PiecesList {
    private:
        unsigned highestLoadedSize;                           // the highest size of pieces currently loaded
        std::vector<std::vector<Piece>> loadedPieces;    // every loaded pieces by size
        std::vector<std::vector<int>> convexPieces;      // the list of convex loaded pieces by size
        std::vector<std::vector<int>> holelessPieces;    // the list of holeless loaded pieces by size
        std::vector<std::vector<int>> otherPieces;       // the list of other loaded pieces by size
        std::vector<std::pair<int, int>> selectedPieces; // the list of all currently selected pieces
        DistributionMode distributionMode;               // the current pieces distribution mode
        std::vector<double> proportionsPerSize;          // the proportion of piece for each sizes
        std::vector<double> customProportionsPerSize;    // the proportion of piece for each sizes when the distribution mode is set to custom

    public:
        /**
         * Initializes a list of pieces up to size 0 (so no pieces)
         */
        PiecesList();

        /**
         * Makes the list load all pieces up to the specified size
         * @return If all pieces up to the specified size are correctly loaded
         */
        [[nodiscard]] bool loadPieces(unsigned max_size);

        /**
         * Selects the specified piece
         * @return If the piece could be selected
         */
        bool selectPiece(unsigned size, unsigned number);

        /**
         * Selects all pieces of the specified size
         * @return If the pieces could be selected
         */
        bool selectAllPieces(unsigned size);

        /**
         * Selects all convex pieces of the specified size
         * @return If the pieces could be selected
         */
        bool selectConvexPieces(int size);

        /**
         * Selects all holeless pieces of the specified size
         * @return If the pieces could be selected
         */
        bool selectHolelessPieces(int size);

        /**
         * Selects all other pieces of the specified size
         * @return If the pieces could be selected
         */
        bool selectOtherPieces(int size);

        /**
         * Unselects all previously selected pieces
         */
        void unselectAll();

        /**
         * Changes the current pieces distribution mode
         * @return If the mode is supported
         */
        bool setDistributionMode(DistributionMode distributionMode);

        /**
         * Changes the distribution of the specified size for when the distribution mode is set to custom,
         * the specified distribution must lower or equal to 1
         * @return If the new distribution was applied
         */
        bool changeCustomDistribution(int size, double distribution);

        /**
         * @return The highest loaded size of pieces
         */
        int getHighestLoadedSize() const;

        /**
         * @return The number of pieces of the specified size
         */
        int getNumberOfPieces(int size) const;

        /**
         * @return A copy of the indexes of all selected pieces
         */
        std::vector<std::pair<int, int>> getSelectedPieces() const;

        /**
         * @return The current distribution mode
         */
        DistributionMode getDistributionMode() const;

        /**
         * @return The proportion of pieces for each loaded size
         */
        std::vector<double> getProportionsPerSize() const;

        /**
         * @return A copy of the piece corresponding to the specified index
         */
        Piece getPiece(const std::pair<int, int>& pieceIndex) const;

        /**
         * @return The piece corresponding to the specified index
         */
        const Piece& lookAtPiece(const std::pair<int, int>& pieceIndex) const;
    
    private:
        /**
         * Adds empty vectors at the end of every pieces list
         */
        void pushBackEmptyVectors();
};
