#pragma once

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

#include <vector>
#include <memory>
#include <utility>

using PieceBag = std::vector<std::pair<int, int>>;


/**
 * A litteral bag of pieces, in which you take each of its piece randomly one by one then start again with a new bag
 */
class Bag {
    private:
        std::shared_ptr<PiecesList> piecesList;          // the list of loaded pieces
        int highestSize;                                 // the highest size of piece in the bag
        std::vector<std::pair<int, int>> selectedPieces; // the list of pieces that can be given to the player
        DistributionMode distributionMode;               // the distribution mode
        std::vector<double> propotionsPerSize;           // the proportion of pieces for each size
        std::pair<int, int> next;                        // the next piece to give
        std::vector<PieceBag> currentBags;               // for each size, the list of pieces that are still to be taken out before starting a new bag
        std::vector<PieceBag> nextBags;                  // for each size, the list of pieces that have been taken out of the current bag and have been placed in the next
        std::vector<int> sizesBag;                       // the list each of bags that are still to have a piece taken out of them
        std::vector<double> sizesProgression;            // how close each size is to meet its quota of pieces

    public:
        /**
         * Creates a new bag with the pieces currently selected in the piece list
         */
        Bag(const std::shared_ptr<PiecesList>& piecesList);

        /**
         * Ignores the remaining pieces in the current bag and start fresh from a new bag
         */
        void jumpToNextBag();

        /**
         * Looks at what the next picked piece will be, without removing it from the bag
         * @return The next piece
         */
        Piece lookNext();

        /**
         * Picks a new piece from the current bag, removing it from the bag
         * @return The next piece
         */
        Piece getNext();

    private:
        /**
         * Prepares the next picked piece in advance
         */
        void prepareNext();

        /**
         * Gets the next picked piece from the specified bag
         */
        void getNextPieceFromBag(int bagIndex);
};
