#include "Lexesis/automata.h"
#include "Lexesis/driver.h"
#include "Lexesis/re.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>

int main(int argc, char** argv) {
    assert(argc == 3);

    std::vector<std::shared_ptr<lxs::RE> > regexes;
    std::string testname = argv[1];
    std::string outputdir = argv[2];

    std::string line;
    std::ofstream reOut(outputdir + "/" + testname + ".re");
    while (getline(std::cin, line)) {
        std::shared_ptr<lxs::RE> re = lxs::parseRE(line);
        reOut << re->toRe() << std::endl;
        regexes.push_back(re);
    }
    reOut.close();

    std::vector<lxs::ENFA> enfas;
    for (std::size_t i = 0; i < regexes.size(); i++) {
        lxs::ENFA enfa;
        regexes[i]->toENFA(enfa, 0);
        enfa.numStates++;
        enfa.starting = 0;
        enfa.priority[*enfa.accepting.begin()] = i;
        enfa.acceptingToken[*enfa.accepting.begin()] = std::to_string(i);
        enfas.push_back(enfa);
    }

    lxs::ENFA merged = lxs::merge(enfas);
    
    std::ofstream enfaOut(outputdir + "/" + testname + ".enfa");
    enfaOut << lxs::toDot(merged) << std::endl;
    enfaOut.close();

    lxs::DFA dfa = lxs::mssc(merged);
    std::ofstream msscOut(outputdir + "/" + testname + ".mssc");
    msscOut << lxs::toDot(dfa) << std::endl;
    msscOut.close();

    lxs::DFA min = lxs::minimize(dfa);
    std::ofstream minOut(outputdir + "/" + testname + ".min");
    minOut << lxs::toDot(min) << std::endl;
    minOut.close();

    return 0;
}
