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

#include <istream>
#include <string>
#include <iostream>
#include <memory>

namespace lxs {
    DFA InputParser::parseInput(std::istream &is) {
        auto enfavect = parseLines(is);
        auto enfas = linesToEnfa(enfavect);
        auto enfa = merge(enfas);
        auto dfa = mssc(enfa);
        return dfa;
    }

    std::vector<std::pair<std::string,std::string> > InputParser::parseLines(std::istream &is) {
        std::string line;
        std::vector<std::pair<std::string,std::string> > result;
        while(std::getline(is,line)) {
            int loc = line.find_first_of('=');
            int start = line.find_first_not_of(" \t\v\f\r");
            std::string tokenname = line.substr(start, loc);
            int end = tokenname.find_last_not_of(" \t\v\f\r");
            tokenname = tokenname.substr(0,end + 1);
            std::string regex = line.substr(loc+1);
            start = regex.find_first_not_of(" ");
            regex = regex.substr(start);
            result.push_back(std::make_pair(tokenname,regex));
        }
        return result;
    }

    std::vector<ENFA> InputParser::linesToEnfa(std::vector<std::pair<std::string,std::string> > &input) {
        std::vector<ENFA> result;
        for(unsigned int i=0;i<input.size();i++) {
            std::shared_ptr<lxs::RE> re = lxs::parseRE(input[i].second);
            ENFA enfa;
            re->toENFA(enfa,0);
            enfa.numStates++;
            enfa.starting = 0;
            enfa.priority[(State) *enfa.accepting.begin()] = (Priority) i; 
            enfa.acceptingToken[(State) *enfa.accepting.begin()] = input[i].first;
            result.push_back(enfa);
        }

        return result;
    }
}
