class UserAccessLevel:
    ALL = 0
    METADATA = 1
    OBJECT = 2


class DbManager:
    """
    Abstract base class for all database managers
    """


    def connect(self, connectString):
        raise NotImplementedError("Subclass must override")


    def close(self, conn):
        raise NotImplementedError("Subclass must override")
    

    def clean(self, connectString):
        """
        Remove all objects from the database that are not accessible from either
        an extent or a bound name.  In other words, garbage collection.
        """
        raise NotImplementedError("Subclass must override")


    def clear(self, connectString):
        """
        Remove all existing data from the specified database.
        """
        raise NotImplementedError("Subclass must override")


    def create(self, connectString):
        """
        Create a new database ready to accept ODL.
        """
        raise NotImplementedError("Subclass must override")


    def destory(self, connectString):
        """
        Completely removes the database specified by the connectString
        from the system.
        """
        raise NotImplementedError("Subclass must override")


    def grant(self, connectString, username, accessLevel):
        """
        Changes the access level of the given user in the specified database.
        """
        raise NotImplementedError("Subclass must override")

    
    def exists(self, connectString):
        raise NotImplementedError("Subclass must override")

    
    def init(self, connectString):
        raise NotImplementedError("Subclass must override")


    def initRepo(self,connString,adapter):

        from Ft.Ods import Constants
        #Create the initial structure
        db = self.connect(connString)
        adapter.begin(db)

        #Add the extent Tuple
        adapter.addExtent(db,'ftods_types',Constants.Types.ROBJECT)


        #Create the repository, and two sub modules and the types
        from Ft.Ods.MetaData import Repository
        from Ft.Ods.MetaData import Module
        from Ft.Ods.MetaData import PrimitiveType
        from Ft.Ods.MetaData import PrimitiveKind
        from Ft.Ods.MetaData import MetaKind
        from Ft.Ods.MetaData import CollectionKind
        from Ft.Ods.MetaData import Direction
        from Ft.Ods import Collections

        from Ft.Ods import Date,Interval,TimeImp,TimeStamp


        adapter.newPythonClass(db,Repository.Repository)
        adapter.newPythonClass(db,Module.Module)
        adapter.newPythonClass(db,PrimitiveType.PrimitiveType)
        adapter.newPythonClass(db,Collections.LiteralListOfObjects)

        adapter.newPythonLiteralClass(db,Constants.Types.DATE,-1,Date.Date)
        adapter.newPythonLiteralClass(db,Constants.Types.INTERVAL,-1,Interval.Interval)
        adapter.newPythonLiteralClass(db,Constants.Types.TIME,-1,TimeImp.TimeImp)
        adapter.newPythonLiteralClass(db,Constants.Types.TIMESTAMP,-1,TimeStamp.TimeStamp)

        for e in MetaKind.MetaKind.elements:
            adapter.newPythonLiteralClass(db,Constants.Types.ENUMERATION,e._typeId,e.__class__)

        for e in PrimitiveKind.PrimitiveKind.elements:
            adapter.newPythonLiteralClass(db,Constants.Types.ENUMERATION,e._typeId,e.__class__)

        for e in CollectionKind.CollectionKind.elements:
            adapter.newPythonLiteralClass(db,Constants.Types.ENUMERATION,e._typeId,e.__class__)

        for e in Direction.Direction.elements:
            adapter.newPythonLiteralClass(db,Constants.Types.ENUMERATION,e._typeId,e.__class__)

        repoId = adapter.newRepositoryObjectId(db,16,Repository.Repository,rid=1)
        moId = adapter.newRepositoryObjectId(db,11,Module.Module)
        typesId = adapter.newRepositoryObjectId(db,11,Module.Module)
        repoDefinesCid = adapter.newCollection(db,Collections.LiteralListOfObjects,Constants.CollectionTypes.LIST,Constants.Types.ROBJECT,-1)



        #Create and write the types
        typeIds = []
        for pk in PrimitiveKind.PrimitiveKind.elements:
            tid = adapter.newRepositoryObjectId(db,14,PrimitiveType.PrimitiveType)
            adapter.addExtentEntry(db,['ftods_types'],tid)
            typeIds.append(tid)

            adapter.writeRepositoryObject(db,
                                          14,
                                          tid,
                                          PrimitiveType.PrimitiveType._tupleTypes,
                                          PrimitiveType.PrimitiveType._tupleNames,
                                          ((tid,),
                                           (14,),
                                           (pk._n,),
                                           ('Created by Initialization of Repo',),
                                           (repoId,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (0,),
                                           (pk._v,)))


        adapter.writeRepositoryObject(db,
                                      11,
                                      moId,
                                      Module.Module._tupleTypes,
                                      Module.Module._tupleNames,
                                      ((moId,),
                                       (11,),
                                       ('ODLMetaObjects',),
                                       ('Created by Initialization of Repo',),
                                       (repoId,),
                                       (0,)))

        adapter.writeRepositoryObject(db,
                                      11,
                                      typesId,
                                      Module.Module._tupleTypes,
                                      Module.Module._tupleNames,
                                      ((typesId,),
                                       (11,),
                                       ('ODLTypes',),
                                       ('Created by Initialization of Repo',),
                                       (repoId,),
                                       (0,)))




        typeChanges = []
        ctr = 2
        for tid in typeIds:
            typeChanges.append((tid,ctr))
            ctr = ctr + 1
        changes =  [(Constants.CollectionChanges.APPEND,[(moId,0),(typesId,1)] + typeChanges)]
        adapter.writeCollection(db,repoDefinesCid,changes,Constants.CollectionTypes.LIST,Constants.Types.ROBJECT)
        adapter.writeRepositoryObject(db,
                                      16,
                                      repoId,
                                      Repository.Repository._tupleTypes,
                                      Repository.Repository._tupleNames,
                                      ((repoId,),
                                       (16,),
                                       ('Repository',),
                                       ('Created by Initialization of Repo',),
                                       (0,),
                                       (repoDefinesCid,)))



        adapter.commit(db)
        del db
        return





    def reinit(self, connectString, adapter):
        raise NotImplementedError("Subclass must override")


    def new(self, connectString, adapter):
        self.create(connectString)
        self.init(connectString)
        self.initRepo(connectString, adapter)
        return


    def reinitRepo(self, connectString, adapter):
        self.reinit(connectString, adapter)
        self.initRepo(connectString, adapter)
        return
