#pragma once
#ifndef LEXESIS_DRIVER_H
#define LEXESIS_DRIVER_H

#include <memory>
#include <string>

#include "Lexesis/backendmanager.h"

namespace lxs {
    /**
     * The main driver for Lexesis
     */
    class Driver {
        public:
            /**
             * Constructor
             *
             * @param backends The backendmanager, prepared with all needed supported backends
             * @param inputfile An istream which should be read to be used as token rules specifications
             * @param outputdir A string representing the directory where generated files should be places
             * @param language The language to generate output for (backends is queried for this language)
             * @param lexername The name to give to the generated lexer, this gets cleaned to only contains alphanumeric chars or underscore and start with a non-digit (AKA a valid identifier)
             */
            Driver(std::unique_ptr<BackendManager> backends, std::istream& inputfile, std::string outputdir, std::string language, std::string lexername);

            /**
             * Destructor
             */
            ~Driver();

            /**
             * Run this driver, all the preparation should happen when calling the constructor
             *
             * @return The status code this would return if it were a main function
             */
            int run();

        private:
            std::unique_ptr<BackendManager> m_backends;
            std::istream& m_inputfile;
            std::string m_outputdir;
            std::string m_language;
            std::string m_lexername;
    };
    
    /**
     * Used to throw errors when the driver could generate a valid lexer name or find the backend for a language
     */

    class DriverException: public std::exception {
    public:
        DriverException(std::string what);
        virtual const char* what() const throw();

    private:
        std::string m_what;
    };
}

#endif //LEXESIS_DRIVER_H

