#pragma once

#include "klammer_base.h"
#include "html_util.h"
#include "latex_util.h"
#include "machine.h"
#include "heading.h"
#include "font_store.h"

const std::string closed_symbol { "&^#9656;" };
const std::string open_symbol { "&^#9662;" };
inline std::map<std::string, int> html_tags {
    {"kt-part", 0}, {"kt-chapter", 1}, {"h1", 2},
    {"h2", 3}, {"h3", 4}, {"h4", 5},
    {"h5", 6}, {"h6", 7}, {"h7", 8}};

using string_pairs_t = std::vector<std::pair<std::string,std::string>>;

std::string unescape_newlines(const std::string& s);

enum class docstruct_t {
    plain,
    article,
    book
};

inline docstruct_t docstruct(const std::string& name)
{
    if (name == "plain") {
        return docstruct_t::plain;
    } else if (name == "article") {
        return docstruct_t::article;
    } else {
        return docstruct_t::book;
    }
}

class Document_class : public Klammer_base {
public:
    Document_class(Machine& machine);
    ~Document_class() = default;

    void save_string_input_as_file();

    //void create_directory(std::string directory);
    void write(const std::string& filename, const std::string& contents);

    /*
    strings_t get_css_files(
        const std::string& output_dir,
        const std::string& css_text, const strings_t& css_files, bool write_file);
    */

    strings_t get_js_files(
        bool nav, bool include_sks_js,
        const std::string& pages_basenames_filename); // , const std::string& output_dir, bool write_file);

    argmap m_args {};
    void write_basenames_js_file(const std::string& filename, const std::vector<std::string>& basenames);
    std::string create_html_output_directories();
    std::string create_tex_output_directories();

    std::pair<std::vector<std::string>, std::vector<std::string>> 
    html_auxiliary_files(const std::string& output_directory, const std::string& pages_basename_filename,
                         const std::vector<std::string>& custom_css_files);


    void process_input_files();
    std::vector<Heading> insert_section_numbers(const std::string& marker="___NUM___", bool add_to_toc=true);
    void insert_html_caption_numbers();
    std::vector<std::tuple<std::string, std::string, std::string>> reference_list(const std::string& target_marker);
    std::map<std::string, std::string> id_to_caption_number();
    std::map<std::string, std::vector<std::pair<std::string, std::string>>> html_references();
    void resolve_html_references();
    std::string single_page_toc();
    elements_t page(const std::string& body, const std::string& output_dir, int max_level);

    std::string make_single_html_page(const std::string& output_directory);
    std::string make_html_navigation_structure(
        const std::string& output_directory, std::vector<Heading> headings);
    std::string html();
    std::string tex();
    std::string make_help_page();
    std::string color_definitions();
    std::string font_definitions();
    strings_t resolved_font_names();

    Machine m_machine {};

    std::string m_title {};
    std::string m_subtitle {};
    std::string m_page_title {};
    std::string m_author {};
    std::string m_date {};
    std::string m_version {};
    std::string m_logo {};
    
    // bool m_nav = false;
    // bool m_toc = false;
    docstruct_t m_structure = docstruct_t::plain;

    std::string m_text {};
    strings_t m_files {};

    std::string m_output_dir {};

    bool include_css = true;
    bool include_js = true;

    std::string m_css_text {};
    strings_t m_css_filenames {};
    bool m_include_sks_css = true;
    std::string frame_background_color {};
    std::string frame_text_color {};
    std::string nav_background_color {};
    std::string nav_text_color {};

    std::string js_text {};
    strings_t m_js_filenames {};
    bool m_include_sks_js = true;

    strings_t m_font_dirs {};

    std::string m_serif_font {};
    std::string m_sans_font {};
    std::string m_mono_font {};
    float m_font_scale = 1.0f;
    Resolved_font m_resolved_serif {};
    Resolved_font m_resolved_sans {};
    Resolved_font m_resolved_mono {};

    std::string prolog {};
    std::string paper_size {};
    bool m_two_column = false;
    bool landscape = false;
    float leading = 1.0;
    int point_size = 10;
    bool ragged_right = false;
    std::string cover {};

    std::string m_copyright {};
    std::string m_bottom {};

    bool create_output_directory = true;
    std::string output_directory_name {};
    bool resources_in_file = false;
    //bool use_pages_dir = true;

    bool m_toc_only = false;
    std::string m_kt_root_filename {};

    bool m_no_cache = false;

    bool write_files = true;
    std::string m_input_dir {};

    // strings_t sources {};
    Locator loc {};
    std::string sloc {};

    bool m_html_only = false;

    std::vector<std::pair<std::string, std::string>> m_file_components {};
    std::vector<std::pair<std::string, std::string>> m_string_components {};
    std::vector<std::tuple<std::string,std::string,std::string,std::string>> m_toc_components {};

    std::string m_cache_dir {};
};

fs::path parse_input_filename(const std::string& s, const std::string& input_dir);
void write_file(const std::string& filename, const std::string& contents, bool write_files);

/*
std::vector<std::string> combine_files(
    const std::vector<std::string>& filenames, const std::string& output_filename,
    const std::string& prolog="", const std::string& epilog="",
    bool write_file_p=true,
    std::function <std::string(std::string)> processor=nullptr);
*/



