from Ft.Ods import Constants, DateFactory, TimeFactory, Interval, TimeStampFactory, Object

from Ft.Ods import PersistentObject, Enumeration, Structure, Union, FixedString
td = PersistentObject.TupleDefinitions
from Ft.Ods.MetaData import Module

factories = {}


class DummyPersistentObject(Object.Object):


    def __init__(self,db,data):
        Object.Object.__init__(self,db,data)

        if data is None:
            self.__dict__['name'] = ''



    _tupleDefinitions = Object.Object._tupleDefinitions.copy()
    _tupleDefinitions.update({'name':{td.TYPE:Constants.Types.STRING,
                                      },
                              })
    

    _tupleNames = Object.Object._tupleNames + (('name',),)
    _tupleTypes = Object.Object._tupleTypes + ((Constants.Types.STRING,),)

    _localExtents = ()

    _typeId = 100
    _typeIds = (100,)

class DummyElement(Enumeration.EnumElement):
    nameMapping={0:'One',
                 1:'Two',
                 2:'Three',
                 3:'Four',
                 4:'Five',
                 5:'Six',
                 6:'Seven',
                 7:'Eight',
                 8:'Nine',
                 9:'Ten',
                 }
    def __init__(self,db,value):
        if type(value) == type(()):
            value = value[0]
        Enumeration.EnumElement.__init__(self,db,self.nameMapping[value],value,'DummyEnum',101)

class DummyEnum(Enumeration.Enumeration):
    def __init__(self):
        Enumeration.Enumeration.__init__(self,
                                         "DummyEnum",
                                         101,
                                         [DummyElement(None,0),
                                          DummyElement(None,1),
                                          DummyElement(None,2),
                                          DummyElement(None,3),
                                          DummyElement(None,4),
                                          DummyElement(None,5),
                                          DummyElement(None,6),
                                          DummyElement(None,7),
                                          DummyElement(None,8),
                                          DummyElement(None,9),
                                          ])

class DummyFixedString(FixedString.FixedString):
    max_size = 100


class DummyStruct(Structure.Structure):
    _definition = {'foo':(Constants.Types.STRING,'')}
    _typeId = 102
    _typeIds = (102,)
    _tupleNames = ('foo',)
    def __init__(self,db,data):
        Structure.Structure.__init__(self,db,data)

class DummyUnion(Union.Union):
    _switchType = Constants.Types.UNSIGNED_SHORT
    _cases = {1:('foo',Constants.Types.STRING,''),None:('d',Constants.Types.UNSIGNED_SHORT,0)}
    _defaultCase = 1
    _typeId = 112
    _typeIds = (112,)
    _tupleNames = ('foo','d',)


                  
class EnumFactory:
    ctr = 0
    enum = DummyEnum()
    typeId = enum._typeId

    def next(self,db):
        rt = self.enum.elements[self.ctr]
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 0

class UnionFactory:
    ctr = 0
    typeId = DummyUnion._typeId

    def next(self,db):
        rt = DummyUnion(db,(1,"String %d" % self.ctr))
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 0



class StringFactory:
    ctr = 0
    typeId = -1

    def next(self,db):
        st = "String %d" % self.ctr
        self.ctr = self.ctr + 1
        return st

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 0


class FixedStringFactory:
    ctr=1
    typeId = 145

    def next(self,db):
        st = "%d FixedString" % self.ctr
        self.ctr = self.ctr + 1
        fst = DummyFixedString(db,st)
        fst._typeIds = (-1,)
        return fst

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 1



class CharFactory:
    ctr = 65
    typeId = -1
    def next(self,db):
        st = "%s" % chr(self.ctr)
        self.ctr = self.ctr + 1
        return st

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 65

class OctetFactory:
    ctr = 65
    typeId = -1
    def next(self,db):
        rt = self.ctr
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 65

class _DateFactory:
    ctr = 1
    typeId = -1
    def next(self,db):
        rt = DateFactory.calendar_date(2001,05,self.ctr)
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 1

class _TimeFactory:
    ctr = 1
    typeId = -1
    def next(self,db):
        rt = TimeFactory.from_hmsm(10,05,self.ctr,0)
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 1

class IntervalFactory:
    ctr = 1
    typeId = -1
    def next(self,db):
        rt = Interval.Interval(db,self.ctr)
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 1

class _TimeStampFactory:
    ctr = 1
    typeId = -1
    def next(self,db):
        t = TimeFactory.from_hmsm(10,05,self.ctr,0)
        d = DateFactory.calendar_date(2001,05,self.ctr)
        rt = TimeStampFactory.create(d,t)
        self.ctr = self.ctr + 1
        return rt

    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 1


class StructFactory:
    ctr = 0
    typeId = 102
    def next(self,db):
        s = DummyStruct(db,None)
        s.foo = 'Struct %d' % self.ctr
        self.ctr = self.ctr + 1
        return s
    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 0


class BooleanFactory:
    last = 0
    typeId = -1
    def next(self,db):
        if self.last:
            self.last = 0
            return 0
        self.last = 1
        return 1
    def recreate(self,db,v):
        return v

    def reset(self):
        self.ctr = 0

class IntFactory:
    ctr = 0
    typeId = -1
    def next(self,db):
        st = self.ctr
        self.ctr = self.ctr + 1
        return st
    def recreate(self,db,v):
        return v
    def reset(self):
        self.ctr = 0

class FloatFactory:
    ctr = 1.0
    typeId = -1
    def next(self,db):
        st = self.ctr
        self.ctr = self.ctr + 1.0
        return st
    def recreate(self,db,v):
        return float(str(v))
    def reset(self):
        self.ctr = 1.0

class RObjectFactory:
    ctr = 0
    typeId = 1000
    def next(self,db):
        m = Module.Module(db,None)
        m.name = "Module %d" % self.ctr
        self.ctr = self.ctr + 1
        return m

    def recreate(self,db,v):
        return db._4ods_getPersistentObjectById(Constants.Types.ROBJECT,v._4ods_getId())
    def reset(self):
        self.ctr = 0

class PObjectFactory:
    ctr = 0
    typeId = DummyPersistentObject._typeId
    def next(self,db):
        m = DummyPersistentObject(db,None)
        m.name = "DPO %d" % self.ctr
        self.ctr = self.ctr + 1
        return m

    def recreate(self,db,v):
        return db._4ods_getPersistentObjectById(Constants.Types.POBJECT,v._4ods_getId())
    def reset(self):
        self.ctr = 0



factories[Constants.Types.STRING] = StringFactory()
factories[Constants.Types.CHAR] = CharFactory()
factories[Constants.Types.BOOLEAN] = BooleanFactory()
factories[Constants.Types.UNSIGNED_SHORT] = IntFactory()
factories[Constants.Types.SIGNED_SHORT] = IntFactory()
factories[Constants.Types.UNSIGNED_LONG] = IntFactory()
factories[Constants.Types.DOUBLE] = FloatFactory()
factories[Constants.Types.FLOAT] = FloatFactory()
factories[Constants.Types.SIGNED_LONG] = IntFactory()
factories[Constants.Types.SIGNED_LONG_LONG] = IntFactory()
factories[Constants.Types.ROBJECT] = RObjectFactory()
factories[Constants.Types.POBJECT] = PObjectFactory()
factories[Constants.Types.STRUCTURE] = StructFactory()
factories[Constants.Types.DATE] = _DateFactory()
factories[Constants.Types.TIME] = _TimeFactory()
factories[Constants.Types.INTERVAL] = IntervalFactory()
factories[Constants.Types.TIMESTAMP] = _TimeStampFactory()
factories[Constants.Types.OCTET] = OctetFactory()
factories[Constants.Types.ENUMERATION] = EnumFactory()
factories[Constants.Types.UNION] = UnionFactory()
factories[Constants.Types.FIXEDSTRING] = FixedStringFactory()


def GetFactory(st):
    return factories[st]


def recreate(db,fac,values):
    newValues = []
    for v in values:
        newValues.append(fac.recreate(db,v))
    return newValues


class DummyPersistentEnumObject:
    def __init__(self,v):
        self._v = v

class DummyPersistentType2Object:
    def __init__(self):
        from Ft.Ods.MetaData import MetaKind
        self.meta_kind = MetaKind.mk_primitive_type

    def _4ods_getOdmgType(self):
        return Constants.Types.STRING


class DummyPersistentAttribute2Object:

    def __init__(self,db):
        from Ft.Ods.MetaData import MetaKind
        self.meta_kind = MetaKind.mk_attribute
        self.type = DummyPersistentType2Object()
        self._db = db
        self.name = 'name'

    def _4ods_getOdmgType(self):
        return Constants.Types.ROBJECT

    def _4ods_getId(self):
        return 1001


class DummyPersistentRObject:


    def __init__(self,db,data):
        self.__dict__['_repoId'] = 100

        self.__dict__['defines'] = [DummyPersistentAttribute2Object(db)]
        self.inherits = []
        self.meta_kind = DummyPersistentEnumObject(1)
        self.extender = 0
        self._db = db

    def _4ods_setRepositoryId(self,rid):
        self.__dict__['_repoId'] = rid
    def _4ods_getRepositoryId(self):
        return self.__dict__['_repoId']
    _4ods_getId = _4ods_getRepositoryId


    def _4ods_getOdsType(self):
        return Constants.Types.ROBJECT




def Init(db):

    #Register the enumeration class
    tx = db.current()
    tx._4ods_registerNewLiteralClass(Constants.Types.ENUMERATION,101,DummyElement)

    from Ft.Ods import Date,TimeImp,Interval,TimeStamp
    #We need to register the dates because we don't have a full database when this is run
    tx._4ods_registerNewLiteralClass(Constants.Types.DATE,-1,Date.Date)
    tx._4ods_registerNewLiteralClass(Constants.Types.INTERVAL,-1,Interval.Interval)
    tx._4ods_registerNewLiteralClass(Constants.Types.TIME,-1,TimeImp.TimeImp)
    tx._4ods_registerNewLiteralClass(Constants.Types.TIMESTAMP,-1,TimeStamp.TimeStamp)

    tx._4ods_registerNewLiteralClass(Constants.Types.STRUCTURE,102,DummyStruct)

    tx._4ods_registerNewLiteralClass(Constants.Types.UNION,112,DummyUnion)

    tx._4ods_registerNewLiteralClass(Constants.Types.FIXEDSTRING,145,DummyFixedString)

    tx._adapter.newPythonClass(tx._db,DummyPersistentObject)

    ro = DummyPersistentRObject(db,None)
    tx._adapter.newInterfaceStorage(tx._db,ro)
