#include "argv.h"
#include "command.h"
#include "error.h"
#include "file.h"
#include "font_store.h"
#include "ktype.h"
#include "log.h"
#include "argtype_set.h"
#include "character.h"
#include "show.h"
#include "util.h"

static void font_usage()
{
    std::cout <<
        "Font maintenance commands:\n"
        "  --font                        List the available fonts\n"
        "  --font list                   The same\n"
        "  --font samples <output-dir>   Write a sample page of the available fonts\n"
        "                                to <output-dir>/index.html\n"
        "  --font samples <input-dir> <output-dir>\n"
        "                                Write a sample page for the (not yet\n"
        "                                installed) font files under <input-dir>\n"
        "  --font install <input-dir>    Install the font files found under\n"
        "                                <input-dir> into the user font directory\n"
        "  --font install <input-dir> <output-dir>\n"
        "                                Install into <output-dir> instead\n"
        "  --font help                   This description\n"
        "\n"
        "Fonts are searched in the directories of the KLAMMERTEXT_FONTS\n"
        "environment variable (colon-separated; default $HOME/.klammertext/fonts)\n"
        "and then in the default font set.\n";
}

static void font_command(const strings_t& words)
{
    std::string verb = words.empty() ? "list" : words[0];
    size_t n = words.size() - (words.empty() ? 0 : 1);
    if (verb == "list" && n == 0) {
        std::cout << boldblack << "Fonts\n" << black << describe_fonts();
    } else if (verb == "samples" && n == 1) {
        std::cout << "Font samples written to "
                  << write_font_samples(words[1]) << "\n";
    } else if (verb == "samples" && n == 2) {
        std::cout << "Font samples written to "
                  << write_font_samples(words[2], words[1]) << "\n";
    } else if (verb == "install" && (n == 1 || n == 2)) {
        std::cout << "Installing fonts from " << words[1] << ":\n"
                  << install_fonts(words[1], n == 2 ? words[2] : "");
    } else if (verb == "help") {
        font_usage();
    } else {
        std::cout << "Unrecognized font command: --font " << join(words, " ")
                  << "\n\n";
        font_usage();
    }
}

int main(int argc, char* argv[])
{
    try {
        set_verbose_level(argc, argv);

        Argv args {};
        args.flag("c", "Special characters");
        args.flag("a", "Argument types");
        args.flag("k", "Katom types");
        args.flag("r", "Katom rewrite patterns");
        args.opt("input", "Input filename", "filename", "", "'text'");
        args.flag("targets", "Show targets defined by the input file");
        args.flag("klammers", "Show klammers defined by the input file");
        args.var("font", "List installed fonts.  Enter \"--font help\" for font maintenance commands.");
        args.opt("v",  "'verbosity'", "n", "0", "'verbosity'");

        if (show_usage(argc, argv)) {
            args.usage(file_basename(argv[0]));
            exit(1);
        }
        auto p = [&](std::string name) { return args.get(name) == "true"; };

        args.parse(argc, argv);
        verbose_level = stoi(args.get("v"));
        if (verbose_level > 0) {
            args.describe();
        }

        if (p("c")) {
            show_special_characters();
            std::cout << "\n";
        }

        if (p("a")) {
            Argtype_set argtypes;
            std::cout << boldblack << "\nStandard klammer argument types\n" << black;
            std::cout << argtypes.describe() << "\n";
        }

        if (p("k")) {
            describe_katoms(verbose_level > 2);
        }

        if (p("r")) {
            describe_rewrite_patterns();
        }

        // The --font subcommands operate on the Klammertext font store
        // (infrastructure) and load no klammer set.
        if (args.given("font")) {
            strings_t words {};
            for (const std::string& w : args.as_vector("font")) {
                if (!w.empty()) {
                    words.push_back(w);
                }
            }
            font_command(words);
            return 0;
        }

        Machine M;

        strings_t input_filenames = resolve_filename_list(args.get("input"));
        std::cout << "input_filenames: " << input_filenames << "\n";
        if (input_filenames.empty()) {
            M.read(fs::path(M.m_state.value("KLAMMERTEXT_HOME") + "/sks/sks.k"));
        } else {
            for (auto fname : input_filenames) {
                std::cout << "Read " << fname << "\n";
                M.read(fs::path(absolute_pathname(fname)));
            }
        }

        if (p("targets")) {
            std::cout << boldblack << "Targets\n" << black << M.m_targets.describe(2, true);
        }

        if (p("klammers")) {
            std::cout << boldblack << "Klammers\n" << black << M.m_klammers.describe(2);
        }

    }
    catch (Error& e) {
        e.print_message();
    }
}
