#ifndef INCLUDED_MODULES_
#define INCLUDED_MODULES_

#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <string>

#include "../support/support.h"
#include "../classes/classes.h"
#include "../scanner/scanner.h"

namespace FBB
{
    class Process;
}

class Modules: private Support
{
    using Set = std::unordered_set<std::string>;
    using Map = std::unordered_map<std::string, int>;

    struct Data
    {
        int idx;                // CLASSES entry index (-1: external module)
        std::string subdir;     // subdir of this module
        std::string modName;    // name of this module
        Set imports;            // modules imported by this module
        Set orgImports;         // copy of imports, used with -d
    };

    using Vect = std::vector<Data>;

    Classes d_classes;          // get the classes dir-names (0 = project)
    Vect d_modules;             // defined modules in a project
    Map d_modIdx;               // with -d: from module name to d_modules idx.
    Scanner d_scanner;
    bool d_dependencies;
    Set d_project;              // modules defined in a project
    Set d_extern;               // modules defined elsewhere

    std::string d_std;
    std::string d_interface_cc;
    std::string d_colors;
    std::string d_location;     // 1st part of the location of compiled files

    static std::string s_compileCmd;

    public:
        Modules();
        void fill();            // fill d_modules
        bool checkCircular();   // avoid circular dependencies
        bool showDeps();
        void compile();         // compile the module.cc files

    private:
        static std::string col2hyphen(std::string const &name);

        void addImports(Set &dest, Data const &data);        
        void inspect(Classes::Info const &info);
        void fillModIdx();
        void scan(Classes::Info const &info, std::string const &fname);

        Vect::iterator removeImports(Vect::iterator from,
                                     Vect::iterator const &next);
        void removeModule(std::string const &modName, Vect::iterator next);
        void compile(FBB::Process &proc, std::string const &objFile);
};
        
#endif
