#ifndef INCLUDED_SCAN_
#define INCLUDED_SCAN_

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

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

class Options;

class Scan: private Support
{
    using Path          = std::filesystem::path;
    using Set           = std::unordered_set<size_t>;

    using ModMap        = std::unordered_map<std::string, size_t>;
    using ModMapIter    = ModMap::iterator;
    using ModMapInsert  = std::pair<ModMapIter, bool>;

    using ModVect          = std::vector<ModData>;
//    using ModVectIter      = ModVect::iterator;

    private:
        Options const &d_options;
        ModVect &d_modVect;     // modules used in a project
        ModMap &d_modNameIdx;   // from module name to d_modVect idx.
    

        Path d_sourcePath;      // path to process (relative to the cwd)
        Scanner d_scanner;
    
        size_t d_nameIdx;       // the index in d_modVect of the current
                                // module name (~0UL if not available)
        size_t d_currentIdx;    // the index in d_modVect of the currently
                                // defining module; ~0UL if not defining 
                                // a module/partition
        size_t d_nr;            // the prefix before the .o filenames

        bool d_exportNeeded;    // importing a partition in a module unit
    

//ObjStructs d_objStructs;

    public:
        Scan(ModVect &modVect, ModMap &modNameIdx);

//        Path const &cwd() const;                                        // .f
                                                                       
//        Vect &modVect();                                                // .f

//        std::string gcmName(size_t idx) const;  // modName as .gcm name // .f
//        Vect const &modVect() const;                                    // .f
//        size_t modVectSize() const;                                     // .f
//        ModData const &modVect(size_t idx) const;                       // .f
//        ModMap &moduleNameIdx();                                        // .f

//ObjStructs const &objStructs() const;                           // .f

        void process(std::string const &source, std::string const &filename);

//void setDepending();

//        void setExtern(size_t idx);                                     // .f
        void setNr(size_t nr);                                          // .f

    private:
        size_t declare(std::string const &name);    // index of entry name:
                                                    // UNKNOWN if new.

        size_t define(std::string const &name);     // UNKNOWN -> LOCAL


        void defineModule();            // MODDEF   export module Name;

        void importModule();            // MODDECL  [export] import Name; 

        void modSource();               // MODSRC   module Name;

        void definePartition();         // PARTDEF  export module Name:Part;
        void importPartition();         // PARTDECL export import :Part;

        void importing(std::string const &name);    // module or partition

//ObjStruct objStruct(size_t idx, ModData const &data) const;

//        void setCompile(ObjStruct &objStr, size_t idx,
//                                           std::string const &source) const;

//        static std::string parents(std::string const &source);

        static size_t idxOf(ModMapInsert const &inserted);              // .ih
};

#include "scan.f"

#endif



