// Copyright (c) 2018-2024 Charlie Vanaret
// Licensed under the MIT license. See LICENSE file in the project directory for details.

#ifndef UNO_INEQUALITYHANDLINGMETHOD_H
#define UNO_INEQUALITYHANDLINGMETHOD_H

#include <string>
#include "linear_algebra/Norm.hpp"

namespace uno {
   // forward declarations
   class Direction;
   class EvaluationCache;
   class Evaluations;
   class SolverWorkspace;
   class GlobalizationStrategy;
   class HessianModel;
   class Iterate;
   class l1RelaxedProblem;
   class OptimizationProblem;
   class Options;
   class InertiaCorrectionStrategy;
   class Statistics;
   class Subproblem;
   class UserCallbacks;
   template <typename ElementType>
   class Vector;
   class WarmstartInformation;
   
   class InequalityHandlingMethod {
   public:
      explicit InequalityHandlingMethod(const Options& options);
      virtual ~InequalityHandlingMethod() = default;

      virtual void initialize(const OptimizationProblem& problem, Iterate& current_iterate,
         HessianModel& hessian_model, InertiaCorrectionStrategy& inertia_correction_strategy, bool uses_trust_region) = 0;
      virtual void initialize_statistics(Statistics& statistics) = 0;
      virtual void generate_initial_iterate(Iterate& initial_iterate, EvaluationCache& evaluation_cache) = 0;
      virtual void solve(Statistics& statistics, Iterate& current_iterate, Direction& direction, double trust_region_radius,
         Evaluations& current_evaluations, WarmstartInformation& warmstart_information) = 0;

      virtual void initialize_feasibility_problem(Iterate& current_iterate) = 0;
      virtual void set_elastic_variable_values(const l1RelaxedProblem& problem, Iterate& current_iterate, Evaluations& evaluations) = 0;
      [[nodiscard]] virtual double proximal_coefficient() const = 0;

      // progress measures
      [[nodiscard]] virtual bool is_iterate_acceptable(Statistics& statistics, GlobalizationStrategy& globalization_strategy,
         Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, double step_length,
         EvaluationCache& evaluation_cache, UserCallbacks& user_callbacks) = 0;

      virtual void postprocess_iterate(Iterate& iterate) = 0;

      virtual void set_initial_point(const Vector<double>& initial_point) = 0;

      size_t number_subproblems_solved{0};

      [[nodiscard]] virtual std::string get_name() const = 0;

   protected:
      const Norm progress_norm;
      // when the parameterization of the subproblem (e.g. penalty or barrier parameter) is updated, signal it
      bool subproblem_definition_changed{false};

      void evaluate_progress_measures(const OptimizationProblem& problem, Iterate& iterate, Evaluations& evaluations) const;
      [[nodiscard]] bool is_iterate_acceptable(Statistics& statistics, GlobalizationStrategy& globalization_strategy,
         const Subproblem& subproblem, const SolverWorkspace& solver_workspace, Iterate& current_iterate, Iterate& trial_iterate,
         const Direction& direction, double step_length, EvaluationCache& evaluation_cache, UserCallbacks& user_callbacks);
   };
} // namespace

#endif // UNO_INEQUALITYHANDLINGMETHOD_H