#include <libtools.h>
#include <anymap.h>
#include <iniparser.h>

typedef std::function<int(com::Anymap*)> IntFunc;
typedef std::function<bool(com::Anymap*)> BoolFunc;
typedef std::function<bool*(com::Anymap*)> BoolArrFunc;  

IntFunc LoadEntry(std::string lib, std::string func) {
    DllHandle handler;
    return com::lib::loadFunction<int (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}

BoolFunc LoadPred(std::string lib, std::string func) {
    DllHandle handler;
    return com::lib::loadFunction<int (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}

BoolArrFunc LoadSelector(std::string lib, std::string func){
    DllHandle handler;
    return com::lib::loadFunction<bool* (com::Anymap*), DllHandle>(lib.c_str(), func.c_str(), handler);
}

void check_pred(bool predval, std::string predname) {
    if (!predval) {
        std::cout<<"Predicate "<<predname<<" returned FALSE!"<<std::endl;
        exit(-1);
    }   
}

int main(int argc, char const *argv[])
{   
    auto data = com::Anymap();
    //Predicates
% for pred in preds:
    auto ${pred} = LoadPred("${pred.module}", "${pred.name}"); 
% endfor
    //Entry functions
% for morph in morphs:
    auto ${str(morph)} = LoadEntry("${morph.module}", "${morph.name}"); 
% endfor
    //Selectors
% for sel in sels:
    auto ${str(sel)} = LoadSelector("${sel.module}", "${sel.name}"); 
% endfor
    //Branch tokens
    bool* SEL_${states[0].name} = new bool[${len(states[0].transfers)}];
    std::fill_n(SEL_${states[0].name}, ${len(states[0].transfers)}, true);
% for st in states[1:]:
    bool* SEL_${st.name} = new bool[${len(st.transfers)}];
    std::fill_n(SEL_${st.name}, ${len(st.transfers)}, false);
% endfor

${body}

TERM:
    std::cout<<"Termination!\n"; 
    return 0;
}