/**
\private
*/
#pragma once
#include "../arhiplex_cpp.h"
#include "../arhiplex_itf.h"
#include "../arhiplex_utils.h"
#include "variable.h"
#include "utils.h"
#include <memory>

namespace arhiplex
{
/**
 \~russian
 * Предоставляет доступ к информации о расчете (количество итераций, статус, значение целевой функции и пр.), 
 * а также к значениям переменных
 \brief Класс для работы с итогами расчета

 \~english
 * Provides access to calculation information (number of iterations, status, objective function value, etc.),
 * as well as to variable values
 \brief Class for working with calculation results

 \~chinese-traditional
 * Provides access to calculation information (number of iterations, status, objective function value, etc.),
 * as well as to variable values
 \brief Class for working with calculation results
 */

class SolveResult
{
  public:
/**
  \private
 */  
    SolveResult(ISolveResult *solve_res) : _solve_res(solve_res, releasable_object_deleter)
    {
    }

    SolveResult(const char* calc_uid, const char* name_mapping_file = "")
        : _solve_res(CreateSolveResult(calc_uid, name_mapping_file), releasable_object_deleter)
    {
    }

/**
 \~russian
 * Получает статус процесса расчетов
  \return Значение статуса

 \~english
 * Gets the status of the calculation process
  \return Status value

 \~chinese-traditional
 * Gets the status of the calculation process
  \return Status value
 */  
    solve_result GetSolveResult() const
    {
        solve_result res = _solve_res->GetSolveResult();
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает статус модели в итоге расчета
  \return Значение статуса

 \~english
  Gets the model status as a result of the calculation
  \return Status value

 \~chinese-traditional
  Gets the model status as a result of the calculation
  \return Status value
 */  
    solution_status GetSolutionStatus() const
    {
        solution_status res = _solve_res->GetSolutionStatus();
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает точность решения в процентах
  \return точность решения в процентах

 \~english
  Gets the solution accuracy in percent
  \return solution accuracy in percent

 \~chinese-traditional
  Gets the solution accuracy in percent
  \return solution accuracy in percent
 */ 	
    double GetRelativeGap() const
    {
        auto res = _solve_res->GetRelativeGap();
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает количество итераций, проведенных в процессе расчета
  \return Кол-во итераций

 \~english
  Gets the number of iterations performed during the calculation
  \return Number of iterations

 \~chinese-traditional
  Gets the number of iterations performed during the calculation
  \return Number of iterations
 */ 	
    unsigned int GetIterationsCount() const
    {
        auto res = _solve_res->GetIterationsCount();
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Получает количество обработанных узлов дерева решений
  \return Кол-во обработанных узлов

 \~english
  Gets the number of processed nodes of the decision tree
  \return Number of processed nodes

 \~chinese-traditional
  Gets the number of processed nodes of the decision tree
  \return Number of processed nodes
 */ 	
    std::int64_t GetProcessedNodesCount() const
    {
        auto res = _solve_res->GetProcessedNodesCount();
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Получает значение целевой функции
  \return Значение целевой функции

 \~english
  Gets the value of the objective function
  \return The value of the objective function

 \~chinese-traditional
  Gets the value of the objective function
  \return The value of the objective function
 */ 	
 
    double GetObjectiveFunctionValue() const
    {
        auto res = _solve_res->GetObjectiveFunctionValue();
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Получает значение граничной (двойственной) функции
  \return Значение граничной (двойственной) функции

 \~english
  Gets the value of the boundary (dual) function
  \return The value of the boundary (dual) function

 \~chinese-traditional
  Gets the value of the boundary (dual) function
  \return The value of the boundary (dual) function
 */ 	
    double GetBestBoundValue() const
    {
        auto res = _solve_res->GetBestBoundValue();
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Получает общее время решения
  \return Общее время решения, секунды

 \~english
  Gets the total solution time
  \return Total solution time, seconds

 \~chinese-traditional
  Gets the total solution time
  \return Total solution time, seconds
 */ 	
    double GetSolveTime() const
    {
        auto res = _solve_res->GetSolveTime();
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение переменной в решении
  \param[in] var переменная
  \return Значение переменной в решении

 \~english
  Gets the value of a variable in the solution
  \param[in] var variable
  \return The value of the variable in the solution

 \~chinese-traditional
  Gets the value of a variable in the solution
  \param[in] var variable
  \return The value of the variable in the solution
 */ 	
    double GetVariableValue(const Variable& var) const
    {
        auto res = _solve_res->GetVariableValue(var.Get());
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Получает значение переменной в решении по имени 
  \param[in] var_name имя переменной
  \return Значение переменной в решении

 \~english
  Gets the value of a variable in the solution by name
  \param[in] var_name variable name
  \return Value of the variable in the solution

 \~chinese-traditional
  Gets the value of a variable in the solution by name
  \param[in] var_name variable name
  \return Value of the variable in the solution
 */ 	
    double GetVariableValue(const char *var_name) const
    {
        auto res = _solve_res->GetVariableValue(var_name);
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение dual value
  \param[in] constr ограничение
  \return Значение dual value

 \~english
  Gets the value of dual value
  \param[in] constr constraint
  \return Value of dual value

 \~chinese-traditional
  Gets the value of dual value
  \param[in] constr constraint
  \return Value of dual value
*/
    double GetDualValue(const Constraint& constr) const
    {
        auto res = _solve_res->GetDualValue(constr.Get());
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение dual value по имени ограничения
  \param[in] constr_name имя ограничения
  \return Значение dual value

 \~english
  Gets the value of dual value by constraint name
  \param[in] constr_name constraint name
  \return Value of dual value

 \~chinese-traditional
  Gets the value of dual value by constraint name
  \param[in] constr_name constraint name
  \return Value of dual value
*/
    double GetDualValue(const char* constr_name) const
    {
        auto res = _solve_res->GetDualValue(constr_name);
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение reduced cost
  \param[in] var переменная
  \return Значение reduced cost

 \~english
  Gets the reduced cost value
  \param[in] var variable
  \return Reduced cost value

 \~chinese-traditional
  Gets the reduced cost value
  \param[in] var variable
  \return Reduced cost value
*/
    double GetReducedCost(const Variable& var) const
    {
        auto res = _solve_res->GetReducedCost(var.Get());
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение reduced cost по имени переменной
  \param[in] var_name имя переменной
  \return Значение reduced cost

 \~english
  Gets the reduced cost value by variable name
  \param[in] var_name variable name
  \return Reduced cost value

 \~chinese-traditional
  Gets the reduced cost value by variable name
  \param[in] var_name variable name
  \return Reduced cost value
*/
    double GetReducedCost(const char* var_name) const
    {
        auto res = _solve_res->GetReducedCost(var_name);
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
  Получает значение выражения
  \param[in] expr линейное выражение
  \return Значение выражения

 \~english
  Gets the value of the expression
  \param[in] expr linear expression
  \return Value of the expression

 \~chinese-traditional
  Gets the value of the expression
  \param[in] expr linear expression
  \return Value of the expression
 */
    double GetExpressionValue(const LinearExpression &expr) const
    {
        auto res = _solve_res->GetExpressionValue(expr.Get());
        CHECKERR(_solve_res);
        return res;
    }

/**
 \~russian
    Получает значение выражения
    \param[in] expr квадратичное выражение
    \return Значение выражения

 \~english
    Gets the value of the expression
    \param[in] expr quadratic expression
    \return Value of the expression

 \~chinese-traditional
    Gets the value of the expression
    \param[in] expr quadratic expression
    \return Value of the expression
    */
    double GetExpressionValue(const QuadExpression& expr) const
    {
        auto res = _solve_res->GetExpressionValue(expr.Get());
        CHECKERR(_solve_res);
        return res;
    }
	
/**
 \~russian
  Записывает решение в файл
 \param[in] file_name путь к файлу решения для записи

 \~english
  Writes the solution to a file
 \param[in] file_name path to the solution file to write

 \~chinese-traditional
  Writes the solution to a file
 \param[in] file_name path to the solution file to write
 */ 	
    void WriteSolution(const char *file_name) const
    {
        _solve_res->WriteSolution(file_name);
        CHECKERR(_solve_res);
    }


  protected: 
    std::shared_ptr<ISolveResult> _solve_res;

};

}