import os,sys,traceback

class CustomRecordFetcher:

    def __init__(self,DBI,SQL,Params=()):
        self.Cur=DBI.CreateCur()
        self.Cur.execute(SQL,Params)
        self.Desc=None
        self.FieldNames=[]
        self._Init()

    def _Init(self):
        pass

    def Fetch(self):
        return self._GetRecord()

class IFaceDB:
    
    def __init__(self,Path):
        self.Con=None
        self.Path=Path
        self.Cur=None
        self._TableIDs={}
        self.LogFileName=''
        
    def _LogSQL(self,Sender,SQL,DTup):    
        if self.LogFileName:
            f=open(self.LogFileName,'a')
            f.write("\nFrom: %s\n"%Sender)
            fr=sys._getframe(0)
            traceback.print_stack(fr,3,f)
            f.write("SQL:\n%s\n"%SQL)
            f.write("Vals:\n%s\n"%str(DTup))
        

    def CreateFetcher(self,SQL,Params=()):
        return None

    def Open(self,ReCreate=False):
        if self.Con: return 0
        if self.LogFileName:
            f=open(self.LogFileName,'w')
            f.close()
        if ReCreate:
            if os.path.exists(self.Path):
                os.remove(self.Path)
        self.Con=self._CreateConnection()
        self.Cur=self._CreateCursor()
        self._AfterOpen()
        return 1
    
    def _AfterOpen(self):
        pass

    def Close(self,RemoveDb=False):
        if not self.Con: return 0
        self._CloseConnection()
        self.Con=None
        self.Cur=None
        if RemoveDb:
            os.remove(self.Path)
            
    def CreateCur(self):
        return self._CreateCursor()
        
    def _CreateConnection(self):
        return None
    
    def _CreateCursor(self):
        return self.Con.cursor()
        
    def GetInsSQL(self,TableName,RDict):
        rks=RDict.keys()
        rkv=[];rkq=[]
        for rk in rks:
            rkv.append(RDict[rk])
            rkq.append('?')
        tup=(TableName,",".join(rks),",".join(rkq))
        sql='INSERT INTO %s (%s) values(%s)'%tup    
        return [sql,tuple(rkv)]

    def GetUpdSQL(self,TableName,RDict,KeyFields):
        rks=RDict.keys()
        rkv=[];rkq=[]
        for rk in rks:
            rkv.append(RDict[rk])
            rkq.append('%s=?'%rk)
        if KeyFields:
            if type(KeyFields) in [type(''),type(u'')]:
                KeyFields=KeyFields.split(',')
            sqw=[]
            for kf in KeyFields:
                rkv.append(RDict[kf])
                sqw.append('%s=?'%kf)
            sqw="WHERE\n%s"%(",\n".join(sqw))    
        else: 
            sqw=''
        tup=(TableName,",\n".join(rkq),sqw)
        sql='UPDATE %s SET %s %s'%tup    
        return [sql,tuple(rkv)]

    def GetDelSQL(self,TableName,RDict,KeyFields):
        rkv=[]
        if KeyFields==None and RDict:
            KeyFields=RDict.keys()
        if KeyFields:
            rks=RDict.keys()
            rkq=[]
            if type(KeyFields) in [type(''),type(u'')]:
                KeyFields=KeyFields.split(',')
            sqw=[]
            for kf in KeyFields:
                rkv.append(RDict[kf])
                sqw.append('%s=?'%kf)
            sqw="WHERE\n%s"%("and\n".join(sqw))
        else: 
            sqw=''
        tup=(TableName,sqw)
        sql='DELETE FROM %s %s'%tup    
        return [sql,tuple(rkv)]
        
    def Fetch(self,SQL,Params=(),RecLimit=-1,CallBackProc=None):
        fo=self.CreateFetcher(SQL,Params)
        recs=[]
        descl=[]
        if CallBackProc: RecLimit=0
        cnt=0
        while True:
            lrow=fo.Fetch()
            if not lrow:
                break
            recs.append(lrow)
            cnt+=1
            if RecLimit>=0:
                if cnt>=RecLimit:
                    if not CallBackProc: return recs
                    if not CallBackProc(recs): return
                    recs=[]
        if RecLimit>=0:
            if recs:
                if not CallBackProc: return recs
                if not CallBackProc(recs): return
                return
            return                            
        return recs

    def GenID(self,Table,KeyField):
        tid=self._TableIDs.get(Table,None)
        if tid==None:
            sql="select max(%s) %s from %s"%(KeyField,KeyField,Table)
            recs=self.Fetch(sql)
            if recs:
                tid=recs[0][KeyField]
                if tid==None: tid=0
            else:
                tid=0
        tid+=1
        self._TableIDs[Table]=tid
        return tid
    
    def StartTr(self):
        pass
    
    def CommitTr(self,Restart=False):
        pass
    
    def RollBackTr(self,Restart=False):
        pass
        
    def _CloseConnection(self):
        pass
    
    def Exec(self,SQL,Params=()):
        self.Cur.execute(SQL,Params)

    def InsRec(self,Table,RecD):
        sql,dtup=self.GetInsSQL(Table,RecD)
        self._LogSQL('InsRec',sql,dtup)
        self.Exec(sql,dtup)

    def UpdRec(self,Table,RecD,Keys=None):
        sql,dtup=self.GetUpdSQL(Table,RecD,Keys)
        self._LogSQL('UpdRec',sql,dtup)
        self.Exec(sql,dtup)

    def DelRec(self,Table,RecD=None,Keys=None):
        sql,dtup=self.GetDelSQL(Table,RecD,Keys)
        self._LogSQL('DelRec',sql,dtup)
        self.Exec(sql,dtup)
        
    def GetRec(self,Table,KeyValD):
        sql='select * from %s'%Table
        if KeyValD:
            sqw=[]
            sqv=[]
            for k,v in KeyValD.items():
                sqw.append('(%s=?)'%k)
                sqv.append(v)
            sqw=" and\n".join(sqw)
            sql2="where\n%s"%sqw
            sql="%s\n%s"%(sql,sql2)
            sqv=tuple(sqv)
        else:
            sqv=()
        self._LogSQL('GetRec',sql,sqv)    
        recs=self.Fetch(sql,sqv,1)
        if recs:
            return recs[0]
        else:    
            return None
        

if __name__=='__main__':
    pass
        