// Copyright (c) 2019 Pantor. All rights reserved.

#ifndef INCLUDE_INJA_ENVIRONMENT_HPP_
#define INCLUDE_INJA_ENVIRONMENT_HPP_

#include <fstream>
#include <memory>
#include <sstream>
#include <string>

#include <nlohmann/json.hpp>

#include "config.hpp"
#include "function_storage.hpp"
#include "parser.hpp"
#include "renderer.hpp"
#include "string_view.hpp"
#include "template.hpp"
#include "utils.hpp"

namespace inja {

using json = nlohmann::json;

/*!
 * \brief Class for changing the configuration.
 */
class Environment {
  std::string input_path;
  std::string output_path;

  LexerConfig lexer_config;
  ParserConfig parser_config;
  RenderConfig render_config;

  FunctionStorage function_storage;
  TemplateStorage template_storage;

public:
  Environment() : Environment("") {}

  explicit Environment(const std::string &global_path) : input_path(global_path), output_path(global_path) {}

  Environment(const std::string &input_path, const std::string &output_path)
      : input_path(input_path), output_path(output_path) {}

  /// Sets the opener and closer for template statements
  void set_statement(const std::string &open, const std::string &close) {
    lexer_config.statement_open = open;
    lexer_config.statement_open_no_lstrip = open + "+";
    lexer_config.statement_open_force_lstrip = open + "-";
    lexer_config.statement_close = close;
    lexer_config.statement_close_force_rstrip = "-" + close;
    lexer_config.update_open_chars();
  }

  /// Sets the opener for template line statements
  void set_line_statement(const std::string &open) {
    lexer_config.line_statement = open;
    lexer_config.update_open_chars();
  }

  /// Sets the opener and closer for template expressions
  void set_expression(const std::string &open, const std::string &close) {
    lexer_config.expression_open = open;
    lexer_config.expression_close = close;
    lexer_config.update_open_chars();
  }

  /// Sets the opener and closer for template comments
  void set_comment(const std::string &open, const std::string &close) {
    lexer_config.comment_open = open;
    lexer_config.comment_close = close;
    lexer_config.update_open_chars();
  }

  /// Sets whether to remove the first newline after a block
  void set_trim_blocks(bool trim_blocks) {
    lexer_config.trim_blocks = trim_blocks;
  }

  /// Sets whether to strip the spaces and tabs from the start of a line to a block
  void set_lstrip_blocks(bool lstrip_blocks) {
    lexer_config.lstrip_blocks = lstrip_blocks;
  }

  /// Sets the element notation syntax
  void set_element_notation(ElementNotation notation) {
    parser_config.notation = notation;
  }

  /// Sets the element notation syntax
  void set_search_included_templates_in_files(bool search_in_files) {
    parser_config.search_included_templates_in_files = search_in_files;
  }

  /// Sets whether a missing include will throw an error
  void set_throw_at_missing_includes(bool will_throw) {
    render_config.throw_at_missing_includes = will_throw;
  }

  Template parse(nonstd::string_view input) {
    Parser parser(parser_config, lexer_config, template_storage);
    return parser.parse(input);
  }

  Template parse_template(const std::string &filename) {
    Parser parser(parser_config, lexer_config, template_storage);
    auto result = Template(parser.load_file(input_path + static_cast<std::string>(filename)));
    parser.parse_into_template(result, input_path + static_cast<std::string>(filename));
    return result;
  }

  std::string render(nonstd::string_view input, const json &data) { return render(parse(input), data); }

  std::string render(const Template &tmpl, const json &data) {
    std::stringstream os;
    render_to(os, tmpl, data);
    return os.str();
  }

  std::string render_file(const std::string &filename, const json &data) {
    return render(parse_template(filename), data);
  }

  std::string render_file_with_json_file(const std::string &filename, const std::string &filename_data) {
    const json data = load_json(filename_data);
    return render_file(filename, data);
  }

  void write(const std::string &filename, const json &data, const std::string &filename_out) {
    std::ofstream file(output_path + filename_out);
    file << render_file(filename, data);
    file.close();
  }

  void write(const Template &temp, const json &data, const std::string &filename_out) {
    std::ofstream file(output_path + filename_out);
    file << render(temp, data);
    file.close();
  }

  void write_with_json_file(const std::string &filename, const std::string &filename_data,
                            const std::string &filename_out) {
    const json data = load_json(filename_data);
    write(filename, data, filename_out);
  }

  void write_with_json_file(const Template &temp, const std::string &filename_data, const std::string &filename_out) {
    const json data = load_json(filename_data);
    write(temp, data, filename_out);
  }

  std::ostream &render_to(std::ostream &os, const Template &tmpl, const json &data) {
    Renderer(render_config, template_storage, function_storage).render_to(os, tmpl, data);
    return os;
  }

  std::string load_file(const std::string &filename) {
    Parser parser(parser_config, lexer_config, template_storage);
    return parser.load_file(input_path + filename);
  }

  json load_json(const std::string &filename) {
    std::ifstream file = open_file_or_throw(input_path + filename);
    json j;
    file >> j;
    return j;
  }

  void add_callback(const std::string &name, unsigned int numArgs, const CallbackFunction &callback) {
    function_storage.add_callback(name, numArgs, callback);
  }

  /** Includes a template with a given name into the environment.
   * Then, a template can be rendered in another template using the
   * include "<name>" syntax.
   */
  void include_template(const std::string &name, const Template &tmpl) {
    template_storage[name] = tmpl;
  }
};

/*!
@brief render with default settings to a string
*/
inline std::string render(nonstd::string_view input, const json &data) {
  return Environment().render(input, data);
}

/*!
@brief render with default settings to the given output stream
*/
inline void render_to(std::ostream &os, nonstd::string_view input, const json &data) {
  Environment env;
  env.render_to(os, env.parse(input), data);
}

} // namespace inja

#endif // INCLUDE_INJA_ENVIRONMENT_HPP_
