#ifndef EDIF_IMPORT_H
#define EDIF_IMPORT_H
#include <string>
#include <list>
#include "edif_parser.h"
#include "hub/hub.h"
#include "hub/structural.h"
#include "hub/attr.h"
#include "hub/location.h"
#include "hub/named.h"
#include "import.h"

// ======================================================================================
class EdifImport: public EdifParserClient, public Import {
    EdifParser parser_;
    // ---------------- location -----------------------------------------------------
    hub::Location dest_;

    // ---------------- context other than Location ----------------------------------
    enum { ExtCtx, DefCtx } libCtx_;		// is this an external or defined library
    hub::StructArch*        theArchImpl_;	// current structure
    hub::number_t  	        portNum_;		// port no of current view
    std::vector<hub::Instance*>  theInstances_;	// current instance
    std::vector<hub::Net*>		 theNets_;		// current net
    std::vector<hub::PortProto*> thePorts_;		// actual port prototype
    EdifIndices             theNetDims_;    // array dims of the actual net
    // ---------------- make a port/net/instance name from an Edif array -------------
    std::string hubName (std::string& nm, EdifIndices& indices);

    // ---------------- Edif indices handling ----------------------------------------
    static bool next (EdifIndices&, const EdifIndices&);
    static int product (const EdifIndices&);

protected:
    virtual void haveLibrary     (std::string libname);
    virtual void  endLibrary     (void);
    virtual void haveExternal    (std::string libname);
    virtual void  endExternal    (void);
    virtual void haveDesign      (std::string designName, std::string cellName, std::string libName);
    virtual void  endDesign      (void);
    virtual void haveCell        (std::string cellName);
    virtual void  endCell        (void);
    virtual void haveView        (std::string viewName);
    virtual void  endView        (void);
    virtual void havePort        (std::string portName, EdifIndices& portDims);
    hub::PortProto* havePort     (std::string portName);
    virtual void endPort	     (void);
    virtual void haveDir	     (std::string portDir);
    virtual void haveInstance    (std::string instName, EdifIndices& portDims, std::string viewName, std::string cellName, std::string libName);
    virtual void  endInstance    (void);    
    virtual bool wantProperty      (propCtx, std::string propName);
    virtual void haveStrProperty   (propCtx, std::string propName, std::string propValue);
    virtual void haveBoolProperty  (propCtx, std::string propName, bool propValue);
    virtual void haveIntProperty   (propCtx, std::string propName, int propValue);
    virtual void haveNet         (std::string netName, EdifIndices& netDims);
    virtual void  endNet         (void);
    virtual void haveJoined      (std::string portName, EdifIndices& portIndices, std::string instName, EdifIndices& instIndices);

    static const hub :: PortProto :: flagsType&  DecodeDir (const std::string&);
public:
    virtual void operator() (std::istream*, const std::string&, std::vector<hub::Location>&);
    //virtual void operator() (hub::Library*,      const std::string& ="");	// filtering ops
    //virtual void operator() (hub::Entity*,       const std::string& ="");
    //virtual void operator() (hub::Architecture*, const std::string& ="");

    EdifImport (hub::Hub* h): parser_(this), dest_(h) {}
   ~EdifImport () {}
    
};
// ======================================================================================
class EdifImpLang: public ImportLang {
public:
    static void enregister (void);
    EdifImpLang (const std::string& n): ImportLang(n) {}
    Import* getImporter (hub::Hub* theHub) { return new EdifImport (theHub); }
    void getDefaults (hub::Hub* h, const std::string& fn, Import::Destinations& dflt);
};

#endif

