#include "Lexesis/driver.h"
#include "Lexesis/inputparser.h"

#include <iostream>
#include <fstream>

namespace {
    /**
     * Filter only valid identifier chars: alphanumeric, and not starting with a digit
     */
    std::string clean(std::string in) {
        std::string s;
        for (char c : in) {
            if ((s.length() && std::isalnum(c)) || std::isalpha(c) || c == '_')
                s += c;
        }
        return s;
    }
}

namespace lxs {
    
    DriverException::DriverException(std::string what): m_what(what) {} 
    const char* DriverException::what() const throw() {
        return m_what.c_str();
    }
    
    Driver::Driver(std::unique_ptr<BackendManager> backends, std::istream& inputfile, std::string outputdir, std::string language, std::string lexername) :
                m_backends(std::move(backends)),
                m_inputfile(inputfile),
                m_outputdir(outputdir),
                m_language(language),
                m_lexername(clean(lexername))
    {}

    Driver::~Driver()
    {}

    int Driver::run() {
        if (!m_lexername.length()) throw DriverException("no valid lexer name possible");
        Backend* back = m_backends->findBackendForLang(m_language);
        if (!back) throw DriverException("Could not find a valid backend for language " + m_language );

        DFA dfa = InputParser::parseInput(m_inputfile);

        back->generateLexer([this](std::string filename) -> std::unique_ptr<std::ostream> {
                    return std::unique_ptr<std::ostream>(new std::ofstream(m_outputdir + "/" + filename));
                },
                m_lexername, dfa);

        return 0;
    }
}
