#include "deftype.h"
#include "error.h"

defmode_t defmode_from_katom(katom_t type)
{
    switch (type) {
        case katom_t::klammer_definition:
        case katom_t::klammer_instance:
            return defmode_t::def_create;
        case katom_t::klammer_override:
            return defmode_t::def_override;
        case katom_t::klammer_default:
            return defmode_t::def_default;
        default:
            throw Internal_error("defmode_from_katom: not a definition type");
    }
}

static const std::map<std::pair<defmode_t,defmode_t>, defmode_result> transition_table {
    // create + create = error
    { {defmode_t::def_create, defmode_t::def_create},
        {false, false, "Klammer NAME already defined at AT"} },
    // create + override = replace with warning
    { {defmode_t::def_create, defmode_t::def_override},
        {true, true, "Klammer NAME at AT overridden"} },
    // create + default = ignore silently
    { {defmode_t::def_create, defmode_t::def_default},
        {false, false, ""} },
    // override + create = error
    { {defmode_t::def_override, defmode_t::def_create},
        {false, false, "Klammer NAME already overridden at AT"} },
    // override + override = replace with warning
    { {defmode_t::def_override, defmode_t::def_override},
        {true, true, "Klammer NAME at AT overridden again"} },
    // override + default = ignore silently
    { {defmode_t::def_override, defmode_t::def_default},
        {false, false, ""} },
    // default + create = replace silently
    { {defmode_t::def_default, defmode_t::def_create},
        {true, false, ""} },
    // default + override = replace with warning
    { {defmode_t::def_default, defmode_t::def_override},
        {true, true, "Default klammer NAME at AT overridden"} },
    // default + default = error
    { {defmode_t::def_default, defmode_t::def_default},
        {false, false, "Default klammer NAME already defined at AT"} }
};

const defmode_result& defmode_transition(defmode_t existing, defmode_t incoming)
{
    auto it = transition_table.find({existing, incoming});
    if (it == transition_table.end()) {
        throw Internal_error("defmode_transition: unknown combination");
    }
    return it->second;
}
