/*
 * Author:          Patrick-Christopher Mattulat
 * Co-Author:       Claude Sonnet 4.6 (LLM)
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2020-08-20
 * Changed:         2026-06-23
 *
 * */

#include <algorithm>
#include <ls-std/core/exception/IllegalArgumentException.hpp>
#include <ls-std/io/logging/LogLevel.hpp>

using ls::standard::core::Class;
using ls::standard::core::IllegalArgumentException;
using ls::standard::io::LogLevel;
using ls::standard::io::LogLevelValue;
using std::find_if;
using std::pair;
using std::string;
using std::string_view;

LogLevel::LogLevel(const LogLevelValue &_value) : Class("LogLevel"), value(_value)
{
  this->_init();
}

LogLevel::LogLevel() : Class("LogLevel")
{
  this->_init();
}

LogLevel::~LogLevel() noexcept = default;

LogLevel &LogLevel::operator=(const LogLevelValue &_value)
{
  this->value = _value;
  return *this;
}

bool LogLevel::operator<(const LogLevelValue &_value) const
{
  return this->value < _value;
}

bool LogLevel::operator<=(const LogLevelValue &_value) const
{
  return this->value <= _value;
}

bool LogLevel::operator>(const LogLevelValue &_value) const
{
  return this->value > _value;
}

bool LogLevel::operator>=(const LogLevelValue &_value) const
{
  return this->value >= _value;
}

bool LogLevel::operator==(const LogLevelValue &_value) const
{
  return this->value == _value;
}

LogLevelValue LogLevel::getValue() const
{
  return this->value;
}

void LogLevel::setLogLevel(const LogLevelValue &_value)
{
  this->value = _value;
}

void LogLevel::setLogLevel(const string &_value)
{
  if (this->_isValidLogLevelString(string_view{_value}))
  {
    this->value = _getValueFromString(_value);
  }
  else
  {
    throw IllegalArgumentException{_value + " is not a valid log level string"};
  }
}

string LogLevel::toString() const
{
  return this->level.at(this->value);
}

LogLevelValue LogLevel::_getValueFromString(const string &_value)
{
  const auto &iterator = find_if(this->level.begin(), this->level.end(), [&_value](const pair<LogLevelValue, string> &_logLevelString) { return _logLevelString.second == _value; });
  const auto &[logLevelEnumValue, logLevelStringRepresentation] = *iterator;

  return iterator != level.end() ? logLevelEnumValue : LogLevelValue{};
}

void LogLevel::_init()
{
  this->level.try_emplace(LogLevelValue::FATAL, "FATAL");
  this->level.try_emplace(LogLevelValue::ERR, "ERROR");
  this->level.try_emplace(LogLevelValue::WARN, "WARN");
  this->level.try_emplace(LogLevelValue::INFO, "INFO");
  this->level.try_emplace(LogLevelValue::DEBUG, "DEBUG");
  this->level.try_emplace(LogLevelValue::TRACE, "TRACE");
}

bool LogLevel::_isValidLogLevelString(const string_view _value) const
{
  bool isValidString{};

  for (const auto &[logLevelEnumValue, logLevelStringRepresentation] : this->level)
  {
    isValidString = logLevelStringRepresentation == _value;

    if (isValidString)
    {
      break;
    }
  }

  return isValidString;
}
