/*****************************************************************//**
 * \file   PricingSubProblemAlgorithmAbstract.h
  * \brief lass representing the second important part of the Chain of Responsibility design pattern (the base handler) that organizes the chain dealing with the choice of the pricing algorithm used when solving the pricing subproblem in column generation.
 *
 * \author talmefta
 * \date   May 2022
 *********************************************************************/
#ifndef PRICINGSUBPROBLEMALGORITHMABSTRACT_H
#define PRICINGSUBPROBLEMALGORITHMABSTRACT_H

#include "PricingSubProblemAlgorithm.h"

 /**
  * \class PricingSubProblemAlgorithmAbstract
  * \brief class representing the second important part of the Chain of Responsibility design pattern (the base handler) that organizes the chain dealing with the choice of the pricing algorithm used when solving the pricing subproblem in column generation.
  */

template<class Instance, class ColumnsType, class DualVariables, class ConstraintType>
class PricingSubProblemAlgorithmAbstract: public PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables, ConstraintType> {

protected:
    Instance&                                                               instance; /**< The studied instance.*/
    DualVariables*                                                    dual_variables; /**< The dual variables value in the restricted master problem.*/
    ColumnsType*                                                existing_rmp_columns;
    vector<Constraint<ConstraintType>*>*                       branching_constraints;
    vector<Constraint<ConstraintType>*>*                       cut_constraints;
    PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables, ConstraintType>* next_algorithm; /**< The next algorithm in the chain of responsibility..*/

    

public:
    /**
     * \brief Constructor.
     *
     */
    PricingSubProblemAlgorithmAbstract(Instance& instance, DualVariables* dual_variables, ColumnsType* existing_rmp_columns, vector<Constraint<ConstraintType>*>* branching_constraints, vector<Constraint<ConstraintType>*>* cut_constraints):
        instance(instance), dual_variables(dual_variables), existing_rmp_columns(existing_rmp_columns), branching_constraints(branching_constraints), cut_constraints(cut_constraints),
        next_algorithm(nullptr) {}

    PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables, ConstraintType>* get_next_algorithm() override {
        return this->next_algorithm;
    }

    /**
    * \brief Sets the next algorithm operator in the chain of responsibility in the base handler class (here, the PricingSubProblemAlgorithmAbstract).
    * \param _next_algorithm : PricingSubProblemAlgorithm<PricingSubProblem>*
    * \return _next_algorithm to let us link the algorithms operators in a convenient way (algorithm1->set_next_algorithm(handler2)->set_next_algorithm(handler3)) : PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables>*.
    */
    PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables, ConstraintType>* set_next_algorithm(PricingSubProblemAlgorithm<Instance, ColumnsType, DualVariables, ConstraintType>* _next_algorithm) override {
        this->next_algorithm = _next_algorithm;
        return this->next_algorithm;
    }

    /**
     * \brief Evaluates if the handler (the algorithm) can handle (solve) the pricing sub-problem based on the code of request.
     *
     * \param request : string
     * \return True if the concrete algorithm can solve the pricing sub-problem, false otherwise.
     */
    virtual bool can_solve(const string& request) const = 0;

    /**
     * Solves the pricing sub-problem and stores the solution in solution.
     * \details This method has to be implemented in the inherent classes.
     * \param request : string
     */
    virtual ColumnsType solve(const string& request, const double time_limit) override {
        if (this->next_algorithm)
            return this->next_algorithm->solve(request, time_limit);
        return ColumnsType();
    }

    /**
     * Checks and updates failed_to_find_favorably_priced_columns after solving the pricing subproblem.
     * \details Has to be implemented by inherent classes depending on the nature of the subproblem wheither it is a minimization or maximization problem.
     * 
     */
    virtual void update_failed_to_find_favorably_priced_columns() = 0;
};

#endif //PRICINGSUBPROBLEMALGORITHMABSTRACT_H

