/** @file

  @section license License

  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 <fstream>
#include <unordered_map>

#include "FileConfigCommand.h"
#include "tsutil/YamlCfg.h"
#include "swoc/TextView.h"
#include "swoc/BufferWriter.h"
#include "swoc/bwf_base.h"

namespace
{
constexpr std::string_view PREFIX{"proxy.config."};
constexpr std::string_view TS_PREFIX{"records."};

constexpr bool                    CREATE_IF_NOT_EXIST{true};
constexpr bool                    DO_NOT_CREATE_IF_NOT_EXIST{false};
const std::pair<bool, YAML::Node> NOT_FOUND{false, {}};

/// We support either passing variables with the prefix 'proxy.config.' or 'records.'
/// Internally we need to use 'records.variable' as the root node starts with 'records' for records
/// configs.
std::string
amend_variable_name(swoc::TextView variable)
{
  std::string var{TS_PREFIX};
  // If the variable is prefixed with "proxy.config" we will remove it and replace it
  // with the records "records." root name.
  if (swoc::TextView{variable}.starts_with(PREFIX)) {
    var += variable.substr(PREFIX.size());
    return var;
  }

  // you may be using "records." already or some other name maybe for a different file.
  // we expect either `ts` or `proxy.config`
  return {variable.data(), variable.size()};
}

/// traffic_ctl should work without the need to pass the filename, so use the data
/// we have to figure out the file path. If the filename is specified in the traffic_ctl
/// arguments, then we use that.
void
fix_filename(std::string &filename)
{
  if (filename.empty()) {
    std::string sysconfdir;
    if (const char *env = getenv("PROXY_CONFIG_CONFIG_DIR")) {
      sysconfdir = Layout::get()->relative(env);
    } else {
      sysconfdir = Layout::get()->sysconfdir;
    }
    filename = Layout::get()->relative_to(sysconfdir, "records.yaml");
  }
}

/// Function to open a file if it exists, if not and is requested we will create the file.
std::string
open_file(std::string const &filename, std::fstream &fs, std::ios_base::openmode mode = std::ios::in | std::ios::out,
          bool create = false)
{
  fs.open(filename, mode);

  if (!fs.is_open()) {
    if (create) {
      fs.clear();
      if (fs.open(filename, std::ios::out); fs.is_open()) {
        return {};
      }
    }
    std::string text;
    return swoc::bwprint(text, "We couldn't open '{}': {}", filename, strerror(errno));
  }
  return {};
}

/// Bunch of mapping flags for the TAGS.
std::string
get_tag(swoc::TextView tag)
{
  static std::vector<std::pair<std::string_view, std::vector<std::string_view>>> const Str_to_Tag{
    {ts::Yaml::YAML_INT_TAG_URI,   {"int", "i", "I", "INT", "integer"}         },
    {ts::Yaml::YAML_FLOAT_TAG_URI, {"float", "f", "F", "FLOAT"}                },
    {ts::Yaml::YAML_STR_TAG_URI,   {"str", "s", "S", "STR", "string", "STRING"}}
  };

  for (auto const &[yaml_tag, strs] : Str_to_Tag) {
    if (auto found = std::find_if(std::begin(strs), std::end(strs), [&tag](auto t) { return tag == t; }); found != std::end(strs)) {
      return std::string{yaml_tag.data(), yaml_tag.size()};
    }
  }

  return std::string{tag.data(), tag.size()};
}

std::string
get_leading_comment()
{
  std::string text;
  std::time_t result = std::time(nullptr);
  return swoc::bwprint(text, "Document modified by traffic_ctl {}", std::asctime(std::localtime(&result)));
}

std::pair<bool, YAML::Node>
search_node(swoc::TextView variable, YAML::Node root, bool create)
{
  auto const key{variable.take_prefix_at('.')};
  auto const key_str = std::string{key.data(), key.size()};
  if (variable.empty()) {
    if (root.IsMap() && root[key_str]) {
      return {true, root[key_str]};
    } else {
      if (create) {
        YAML::Node n;
        root[key_str] = n;
        return {true, n}; // new one created;
      } else {
        return NOT_FOUND;
      }
    }
  }
  if (!root[key_str]) {
    if (create) {
      YAML::Node n;
      root[key_str] = n;
      return search_node(variable, n, create);
    }
  } else {
    return search_node(variable, root[key_str], create);
  }
  return NOT_FOUND;
}
} // namespace

YAML::Node
FlatYAMLAccessor::find_or_create_node(swoc::TextView variable, bool search_all)
{
  if (!search_all) {
    if (_docs.size() == 0) {
      // If nothing in it. Add one, it'll be the new node.
      _docs.emplace_back(YAML::NodeType::Map);
    }
  } else {
    for (auto iter = _docs.rbegin(); iter != _docs.rend(); ++iter) {
      if (auto [found, node] = search_node(variable, *iter, DO_NOT_CREATE_IF_NOT_EXIST); found) {
        return node;
      }
    }
    // We haven't found the node, so we will create a new field in the latest doc.
    if (_docs.size() == 0) {
      // if nothing in it. Add one, it'll be the new node.
      _docs.emplace_back(YAML::NodeType::Map);
    }
    // Use the last doc.
  }

  return search_node(variable, _docs.back(), CREATE_IF_NOT_EXIST).second;
}

std::pair<bool, YAML::Node>
FlatYAMLAccessor::find_node(swoc::TextView variable)
{
  if (_docs.size() > 0) { // make sure there is something
    // We start from the bottom.
    for (auto iter = std::rbegin(_docs); iter != std::rend(_docs); ++iter) {
      if (auto [found, node] = search_node(variable, *iter, DO_NOT_CREATE_IF_NOT_EXIST); found) {
        // found it.
        return {true, node};
      }
    }
  }

  return NOT_FOUND; // couldn't find the node;
}

void
FlatYAMLAccessor::make_tree_node(swoc::TextView variable, swoc::TextView value, swoc::TextView tag, YAML::Emitter &out)
{
  auto const key{variable.take_prefix_at('.')};
  auto const key_str = std::string{key.data(), key.size()};
  if (variable.empty()) {
    out << YAML::BeginMap << YAML::Key << key_str;
    if (!tag.empty()) {
      out << YAML::VerbatimTag(get_tag(tag));
    }
    out << YAML::Value << std::string{value.data(), value.size()} << YAML::EndMap;
  } else {
    out << YAML::BeginMap << YAML::Key << key_str;
    make_tree_node(variable, value, tag, out);
    out << YAML::EndMap;
  }
}

FileConfigCommand::FileConfigCommand(ts::Arguments *args) : CtrlCommand(args)
{
  BasePrinter::Options printOpts{parse_print_opts(args)};
  _printer = std::make_unique<GenericPrinter>(printOpts);
  if (args->get(SET_STR)) {
    _invoked_func = [&]() { config_set(); };
  } else if (args->get(GET_STR)) {
    _invoked_func = [&]() { config_get(); };
  } else {
    throw std::invalid_argument("Can't deal with the provided arguments");
  }
}

void
FileConfigCommand::config_get()
{
  auto filename = get_parsed_arguments()->get(COLD_STR).value(); // could be empty which means we should use the default file name
  auto const &data = get_parsed_arguments()->get(GET_STR);
  std::string text;

  fix_filename(filename);
  try {
    FlatYAMLAccessor::load(YAML::LoadAllFromFile(filename));

    for (auto const &var : data) { // we support multiple get's
      auto [found, search] = find_node(amend_variable_name(var));

      if (found) {
        _printer->write_output(swoc::bwprint(text, "{}: {}", var, search.as<std::string>()));
      } else {
        _printer->write_output(swoc::bwprint(text, "{} not found", var));
      }
    }
  } catch (YAML::Exception const &ex) {
    throw std::logic_error(swoc::bwprint(text, "config get error: {}", ex.what()));
  }
}

void
FileConfigCommand::config_set()
{
  static const std::string CREATE_STR{"create"};
  static const std::string TYPE_STR{"type"};

  auto filename = get_parsed_arguments()->get(COLD_STR).value(); // could be empty which means we should use the default file name
  bool append   = !get_parsed_arguments()->get(UPDATE_STR);
  auto const &data = get_parsed_arguments()->get(SET_STR);

  std::string passed_tag;
  if (auto p = get_parsed_arguments()->get(TYPE_STR); p) {
    passed_tag = p.value();
  }
  // Get the default records.yaml if nothing is passed.
  fix_filename(filename);
  if (filename.empty()) {
    throw std::logic_error("Can't deduce the file path.");
  }

  std::ios_base::openmode mode = std::ios::in | std::ios::out;
  if (append) {
    mode = std::ios::out | std::ios::app;
  }

  std::fstream fs;
  if (auto err = open_file(filename, fs, mode, true); !err.empty()) {
    throw std::logic_error(err);
  }

  std::string const &variable = amend_variable_name(data[0]);
  try {
    if (append) {
      YAML::Emitter doc; // we will build the document again, either to append the
                         // new node or to modify the existing one.
      doc << YAML::Comment(get_leading_comment()) << YAML::BeginDoc;
      make_tree_node(variable, data[1], passed_tag, doc);
      doc << YAML::Newline;

      fs.write(doc.c_str(), doc.size());
      fs.close();
    } else {
      FlatYAMLAccessor::load(YAML::LoadAll(fs));
      fs.close();

      auto new_node = find_or_create_node(variable);

      new_node = data[1];

      if (!passed_tag.empty()) {
        new_node.SetTag(get_tag(passed_tag));
      }
      // try gain
      if (auto err = open_file(filename, fs, std::ios::out | std::ios::trunc); !err.empty()) {
        throw std::logic_error(err);
      }

      YAML::Emitter doc;
      YAML::Node    last_node;
      if (_docs.size() > 0) {
        last_node = _docs.back();
        _docs.pop_back();
      }

      for (auto const &n : _docs) {
        if (!n.IsNull()) {
          doc << n;
        }
      }

      if (doc.size() > 0) {
        // There is something already, so add a new line.
        doc << YAML::Newline;
      }
      doc << YAML::Comment(get_leading_comment()) << YAML::BeginDoc << last_node << YAML::Newline;

      fs.write(doc.c_str(), doc.size());
      fs.close();
    }
    std::string text;
    _printer->write_output(swoc::bwprint(text, "Set {}", variable));
  } catch (std::exception const &ex) {
    if (fs.is_open()) {
      fs.close();
    }
    throw ex;
  }
}
