#ifndef MCALC_MCALC_H
#define MCALC_MCALC_H

#include <vector>
#include <optional>
#include <variant>
#include <chrono>
#include <list>
#include <map>
#include <unordered_set>

#include <imgui.h>
#include <imgui_stdlib.h>
#include <node.h>
#include <json.hpp>

namespace ImGui {
    static void TextUnformatted(const std::string &str) {
        const char *start = str.c_str();
        const char *end = start + str.length();
        TextUnformatted(start, end);
    }
}

void draw_menu_bar();
void draw_window();

struct Variable {
    std::unique_ptr<Node> node;
    std::string name, expr;
    std::unordered_set<std::string> depends_on;
    std::optional<double> value;
};

struct State {
    using clock = std::chrono::high_resolution_clock;

    std::vector<std::string> history;
    std::map<std::string, Variable> vars;
    std::string input_buf;
    std::optional<std::string> error;
    std::optional<clock::duration> last_eval_duration;
    std::vector<std::string>::size_type history_entry = 0;

    void handle_input();
    void eval();
    void clear();

    void to_json(nlohmann::json &j) const;
    void from_json(const nlohmann::json &j);
};
extern State state;

template<class> inline constexpr bool always_false_v = false;

class SpaceNumpunct : public std::numpunct<char> {
protected:
    char do_decimal_point() const override { return '.'; }
    char do_thousands_sep() const override { return ' '; }
    std::string do_grouping() const override { return "\03"; }
};

#endif //MCALC_MCALC_H
