/**
 * @file Logger.cpp
 * Logger class implementation
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "core/logging/LoggerConfiguration.h"

#include <sys/stat.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <memory>
#include <map>
#include <string>

#include "core/Core.h"
#include "utils/StringUtils.h"
#include "utils/ClassUtils.h"
#include "utils/file/FileUtils.h"
#include "utils/Environment.h"

#include "spdlog/spdlog.h"
#include "spdlog/sinks/stdout_sinks.h"
#include "spdlog/sinks/null_sink.h"

#ifdef WIN32
#include "core/logging/WindowsEventLogSink.h"
#else
#include "spdlog/sinks/syslog_sink.h"
#endif

#ifdef WIN32
#include <direct.h>
#define _WINSOCKAPI_
#include <windows.h>
#include <tchar.h>
#endif

namespace org {
namespace apache {
namespace nifi {
namespace minifi {
namespace core {
namespace logging {

const char* LoggerConfiguration::spdlog_default_pattern = "[%Y-%m-%d %H:%M:%S.%e] [%n] [%l] %v";

std::vector<std::string> LoggerProperties::get_keys_of_type(const std::string &type) {
  std::vector<std::string> appenders;
  std::string prefix = type + ".";
  for (auto const & entry : properties_) {
    if (entry.first.rfind(prefix, 0) == 0 && entry.first.find(".", prefix.length() + 1) == std::string::npos) {
      appenders.push_back(entry.first);
    }
  }
  return appenders;
}

LoggerConfiguration::LoggerConfiguration()
    : root_namespace_(create_default_root()),
      loggers(std::vector<std::shared_ptr<LoggerImpl>>()),
      shorten_names_(false),
      formatter_(std::make_shared<spdlog::pattern_formatter>(spdlog_default_pattern)) {
  controller_ = std::make_shared<LoggerControl>();
  logger_ = std::shared_ptr<LoggerImpl>(
      new LoggerImpl(core::getClassName<LoggerConfiguration>(), controller_, get_logger(nullptr, root_namespace_, core::getClassName<LoggerConfiguration>(), formatter_)));
  loggers.push_back(logger_);
}

void LoggerConfiguration::initialize(const std::shared_ptr<LoggerProperties> &logger_properties) {
  std::lock_guard<std::mutex> lock(mutex);
  root_namespace_ = initialize_namespaces(logger_properties);
  std::string spdlog_pattern;
  if (!logger_properties->get("spdlog.pattern", spdlog_pattern)) {
    spdlog_pattern = spdlog_default_pattern;
  }

  /**
   * There is no need to shorten names per spdlog sink as this is a per log instance.
   */
  std::string shorten_names_str;
  if (logger_properties->get("spdlog.shorten_names", shorten_names_str)) {
    utils::StringUtils::StringToBool(shorten_names_str, shorten_names_);
  }

  formatter_ = std::make_shared<spdlog::pattern_formatter>(spdlog_pattern);
  std::map<std::string, std::shared_ptr<spdlog::logger>> spdloggers;
  for (auto const & logger_impl : loggers) {
    std::shared_ptr<spdlog::logger> spdlogger;
    auto it = spdloggers.find(logger_impl->name);
    if (it == spdloggers.end()) {
      spdlogger = get_logger(logger_, root_namespace_, logger_impl->name, formatter_, true);
      spdloggers[logger_impl->name] = spdlogger;
    } else {
      spdlogger = it->second;
    }
    logger_impl->set_delegate(spdlogger);
  }
  logger_->log_debug("Set following pattern on loggers: %s", spdlog_pattern);
}

std::shared_ptr<Logger> LoggerConfiguration::getLogger(const std::string &name) {
  std::lock_guard<std::mutex> lock(mutex);
  std::string adjusted_name = name;
  const std::string clazz = "class ";
  auto haz_clazz = name.find(clazz);
  if (haz_clazz == 0)
    adjusted_name = name.substr(clazz.length(), name.length() - clazz.length());
  if (shorten_names_) {
    utils::ClassUtils::shortenClassName(adjusted_name, adjusted_name);
  }

  std::shared_ptr<LoggerImpl> result = std::make_shared<LoggerImpl>(adjusted_name, controller_, get_logger(logger_, root_namespace_, adjusted_name, formatter_));
  loggers.push_back(result);
  return result;
}

std::shared_ptr<internal::LoggerNamespace> LoggerConfiguration::initialize_namespaces(const std::shared_ptr<LoggerProperties> &logger_properties) {
  std::map<std::string, std::shared_ptr<spdlog::sinks::sink>> sink_map = logger_properties->initial_sinks();

  std::string appender_type = "appender";
  for (auto const & appender_key : logger_properties->get_keys_of_type(appender_type)) {
    std::string appender_name = appender_key.substr(appender_type.length() + 1);
    std::string appender_type;
    if (!logger_properties->get(appender_key, appender_type)) {
      appender_type = "stderr";
    }
    std::transform(appender_type.begin(), appender_type.end(), appender_type.begin(), ::tolower);

    if ("nullappender" == appender_type || "null appender" == appender_type || "null" == appender_type) {
      sink_map[appender_name] = std::make_shared<spdlog::sinks::null_sink_st>();
    } else if ("rollingappender" == appender_type || "rolling appender" == appender_type || "rolling" == appender_type) {
      std::string file_name;
      if (!logger_properties->get(appender_key + ".file_name", file_name)) {
        file_name = "minifi-app.log";
      }
      std::string directory;
      if (!logger_properties->get(appender_key + ".directory", directory)) {
        // The below part assumes logger_properties->getHome() is existing
        // Cause minifiHome must be set at MiNiFiMain.cpp?
        directory = logger_properties->getHome() + utils::file::FileUtils::get_separator() + "logs";
      }

      if (utils::file::FileUtils::create_dir(directory) == -1) {
        std::cerr << directory << " cannot be created\n";
        exit(1);
      }
      file_name = directory + utils::file::FileUtils::get_separator() + file_name;

      int max_files = 3;
      std::string max_files_str = "";
      if (logger_properties->get(appender_key + ".max_files", max_files_str)) {
        try {
          max_files = std::stoi(max_files_str);
        } catch (const std::invalid_argument &) {
        } catch (const std::out_of_range &) {
        }
      }

      int max_file_size = 5 * 1024 * 1024;
      std::string max_file_size_str = "";
      if (logger_properties->get(appender_key + ".max_file_size", max_file_size_str)) {
        try {
          max_file_size = std::stoi(max_file_size_str);
        } catch (const std::invalid_argument &) {
        } catch (const std::out_of_range &) {
        }
      }
      sink_map[appender_name] = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(file_name, max_file_size, max_files);
    } else if ("stdout" == appender_type) {
      sink_map[appender_name] = spdlog::sinks::stdout_sink_mt::instance();
    } else if ("stderr" == appender_type) {
      sink_map[appender_name] = spdlog::sinks::stderr_sink_mt::instance();
    } else if ("syslog" == appender_type) {
      sink_map[appender_name] = LoggerConfiguration::create_syslog_sink();
    } else {
      sink_map[appender_name] = LoggerConfiguration::create_fallback_sink();
    }
  }

  std::shared_ptr<internal::LoggerNamespace> root_namespace = std::make_shared<internal::LoggerNamespace>();
  std::string logger_type = "logger";
  for (auto const & logger_key : logger_properties->get_keys_of_type(logger_type)) {
    std::string logger_def;
    if (!logger_properties->get(logger_key, logger_def)) {
      continue;
    }
    bool first = true;
    spdlog::level::level_enum level = spdlog::level::info;
    std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks;
    for (auto const & segment : utils::StringUtils::split(logger_def, ",")) {
      std::string level_name = utils::StringUtils::trim(segment);
      if (first) {
        first = false;
        std::transform(level_name.begin(), level_name.end(), level_name.begin(), ::tolower);
        if ("trace" == level_name) {
          level = spdlog::level::trace;
        } else if ("debug" == level_name) {
          level = spdlog::level::debug;
        } else if ("warn" == level_name) {
          level = spdlog::level::warn;
        } else if ("critical" == level_name) {
          level = spdlog::level::critical;
        } else if ("error" == level_name) {
          level = spdlog::level::err;
        } else if ("off" == level_name) {
          level = spdlog::level::off;
        }
      } else {
        sinks.push_back(sink_map[level_name]);
      }
    }
    std::shared_ptr<internal::LoggerNamespace> current_namespace = root_namespace;
    if (logger_key != "logger.root") {
      for (auto const & name : utils::StringUtils::split(logger_key.substr(logger_type.length() + 1, logger_key.length() - logger_type.length()), "::")) {
        auto child_pair = current_namespace->children.find(name);
        std::shared_ptr<internal::LoggerNamespace> child;
        if (child_pair == current_namespace->children.end()) {
          child = std::make_shared<internal::LoggerNamespace>();
          current_namespace->children[name] = child;
        } else {
          child = child_pair->second;
        }
        current_namespace = child;
      }
    }
    current_namespace->level = level;
    current_namespace->has_level = true;
    current_namespace->sinks = sinks;
  }
  return root_namespace;
}

std::shared_ptr<spdlog::logger> LoggerConfiguration::get_logger(std::shared_ptr<Logger> logger, const std::shared_ptr<internal::LoggerNamespace> &root_namespace, const std::string &name,
                                                                std::shared_ptr<spdlog::formatter> formatter, bool remove_if_present) {
  std::shared_ptr<spdlog::logger> spdlogger = spdlog::get(name);
  if (spdlogger) {
    if (remove_if_present) {
      spdlog::drop(name);
    } else {
      return spdlogger;
    }
  }
  std::shared_ptr<internal::LoggerNamespace> current_namespace = root_namespace;
  std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks = root_namespace->sinks;
  spdlog::level::level_enum level = root_namespace->level;
  std::string current_namespace_str = "";
  std::string sink_namespace_str = "root";
  std::string level_namespace_str = "root";
  for (auto const & name_segment : utils::StringUtils::split(name, "::")) {
    current_namespace_str += name_segment;
    auto child_pair = current_namespace->children.find(name_segment);
    if (child_pair == current_namespace->children.end()) {
      break;
    }
    current_namespace = child_pair->second;
    if (current_namespace->sinks.size() > 0) {
      sinks = current_namespace->sinks;
      sink_namespace_str = current_namespace_str;
    }
    if (current_namespace->has_level) {
      level = current_namespace->level;
      level_namespace_str = current_namespace_str;
    }
    current_namespace_str += "::";
  }
  if (logger != nullptr) {
    logger->log_debug("%s logger got sinks from namespace %s and level %s from namespace %s", name, sink_namespace_str, spdlog::level::level_names[level], level_namespace_str);
  }
  spdlogger = std::make_shared<spdlog::logger>(name, begin(sinks), end(sinks));
  spdlogger->set_level(level);
  spdlogger->set_formatter(formatter);
  spdlogger->flush_on(std::max(spdlog::level::info, current_namespace->level));
  try {
    spdlog::register_logger(spdlogger);
  } catch (const spdlog::spdlog_ex &) {
    // Ignore as someone else beat us to registration, we should get the one they made below
  }
  return spdlog::get(name);
}

std::shared_ptr<spdlog::sinks::sink> LoggerConfiguration::create_syslog_sink() {
#ifdef WIN32
  return std::make_shared<internal::windowseventlog_sink>("ApacheNiFiMiNiFi");
#else
  return std::make_shared<spdlog::sinks::syslog_sink>("ApacheNiFiMiNiFi");
#endif
}

std::shared_ptr<spdlog::sinks::sink> LoggerConfiguration::create_fallback_sink() {
  if (utils::Environment::isRunningAsService()) {
    return LoggerConfiguration::create_syslog_sink();
  } else {
    return spdlog::sinks::stderr_sink_mt::instance();
  }
}

std::shared_ptr<internal::LoggerNamespace> LoggerConfiguration::create_default_root() {
  std::shared_ptr<internal::LoggerNamespace> result = std::make_shared<internal::LoggerNamespace>();
  result->sinks = std::vector<std::shared_ptr<spdlog::sinks::sink>>();
  result->sinks.push_back(spdlog::sinks::stderr_sink_mt::instance());
  result->level = spdlog::level::info;
  return result;
}

} /* namespace logging */
} /* namespace core */
} /* namespace minifi */
} /* namespace nifi */
} /* namespace apache */
} /* namespace org */
