#ifndef FUNCTION_ARGUMENT_CONVERTER_HPP
#define FUNCTION_ARGUMENT_CONVERTER_HPP

#include <DataVariant.hpp>
#include <node_processor/ExecutionPolicy.hpp>

class IFunctionArgumentConverter
{
 public:
  virtual DataVariant convert(ExecutionPolicy& exec_policy, DataVariant&& value) = 0;

  virtual ~IFunctionArgumentConverter() = default;
};

template <typename ExpectedValueType, typename ProvidedValueType>
class FunctionArgumentConverter final : public IFunctionArgumentConverter
{
 private:
  size_t m_argument_id;

 public:
  DataVariant
  convert(ExecutionPolicy& exec_policy, DataVariant&& value)
  {
    if constexpr (std::is_same_v<ExpectedValueType, ProvidedValueType>) {
      exec_policy.currentContext()[m_argument_id] = std::move(value);
    } else if constexpr (std::is_same_v<ExpectedValueType, std::string>) {
      exec_policy.currentContext()[m_argument_id] = std::move(std::to_string(std::get<ProvidedValueType>(value)));
    } else {
      exec_policy.currentContext()[m_argument_id] =
        std::move(static_cast<ExpectedValueType>(std::get<ProvidedValueType>(value)));
    }
    return {};
  }

  FunctionArgumentConverter(size_t argument_id) : m_argument_id{argument_id} {}
};

#endif   // FUNCTION_ARGUMENT_CONVERTER_HPP