from copy import copy

class virtual:
    "this method is unimplemented in this base class"

class table_info_template:
    "reads info about a table, to create widgets about it"
    
    ##
    def __init__(self,db,db_name,table_name):
        """
        the method of initizialization is:
        def __init__(self,db,db_name,table_name):
        where 'db' can be obtained by
        db=MySQLdb.connect() or other module that implements python db api """
        #######dictionaries:

        #a description  is  a sequence of 7-uples of the form
        #(name, type_code, display_size, internal_size, precision, scale, null_ok)
    
        ##field to description
        ##where 'description' is the 7-uple above
        self.field_description={}
    
        ## field to columninfo
        ## where     columninfo = (Field, Type, Null, Key, Default, Extra)
        ##note that the above is the format used by mySQL
        self.field_columninfo={}


        ####### other info:
        ##list of field names
        self.fields=[]
        #and number of fields
        self.n_fields=0
    
        ##default row
        self.default_row=[]
    
        ## some special Fields
        ##list of fields which are part of the primary key
        self.primary_key_fields=[]
        ##and the index of the last one in the list 'fields'
        self.n_primary=None

        ##list of fields which have keys
        self.key_fields=[]
        ##and the index of the last one in the list 'fields'
        self.n_key=None
        




class entry_widget_template:
    "template for class for a row entry (that is, for the value of a column)"

    def __init__(self,columninfo,description):
        (Field, Type, Null, Key, Default, Extra) = columninfo
        (name, type_code, display_size, internal_size, precision, scale, null_ok)=description

        #widget that implements the GUI
        self.widget=None
        #or also
        self.__widget=None


        self.columninfo=copy(columninfo)
        self.description=copy(description)
        #can this entry be null?
        self.not_null=not null_ok
        
        #FIXME not portable?
        self.type=Type
        self.default=Default

        
        #self.key = Key
        
    #standard methods of this class
    def set(self,value):
        #puts the value in the appropriate widget
        raise virtual
    def get(self):
        #gets the value from the widget
        raise virtual
    def set_editable(self,flag):
        #sets the widget so that it can/cannot be edited
        raise virtual

    def log(self,level,text):
        print "LOG("+str(level)+"): "+ text

    
class row_widget_template:
    """template for class for a row (that is, for the value of a row).    
    Note that a row_widget class implements the methods of
    an entry_widget class ---    and can be used as such, for joins"""

    def __init__ (self):
        #widget that implements the GUI
        self.widget=None
        #or
        self.__widget=None

        ## database of joins   localfield   ->   (remotetable,remotefield)
        self.field_join={}
        ## database of joins   remotetable   ->   localfield
        self.join_field={}
        ##database of entries  field   ->  entry 
        self.field_entry={}


    #methods
    def get(self):
        "return the value of the primary"
        return self.primary    
    def set(self,v):
        "it does an SQL SELECT to find the row where primary key=v"
        raise virtual

    def get_row(self):
        raise virtual
    def set_row(self,r):
        raise virtual
        
    def set_editable(self,flag):
        "sets the widget so that it can/cannot be edited"
        raise virtual

    def form_save(self,z,ignore):
        """if ignore is a list, it is a list of (table,field) to ingnore
        if it is -1, it will not follow joins"""
        p=None
        if len(self.primary_key_fields)==1:
            p=self.fields[self.n_primary]
        for f in self.fields:
            if f != p:
                columninfo=self.field_columninfo[f]
                #description=self.field_description[f]
                (Field, Type, Null, Key, Default, Extra) = columninfo
                if ignore != -1 and self.field_join.has_key(f) and \
                       self.field_join[f] not in ignore:
                    ignore.append(self.field_join[f])
                    self.field_entry[f].form_save(z,ignore)
                else:
                    z.write('[['+self.db_name+"/"+self.table_name+'/'+Field+']]=')
                    if Type == 'datetime':
                        z.write('YYYY-MM-DD HH:MM:SS\n')
                    elif Type == 'date':
                        z.write('YYYY-MM-DD\n')
                    else:
                        z.write('\n')

    def insert_DTE(self,D,C):
        "insert data.  D = 'db/table/entry'   C=content "
        zz=D.split('/')
        if len(zz) != 3:
            print "WRONG DTE '"+D+"'"
            return
        (d,t,e)=zz
        if C and C[-1] == '\n' :
            C=C[:-1]
        if d != self.db_name:
            self.log(2,'wrong DB '+d)
            return None
        if t != self.table_name:
            self.log(0,'(ignored entry for table '+t+')')
            return (t,e)
        if not self.field_entry.has_key(e):
            self.log(2,'There is no entry '+e+' in this table!')
            return None
        self.field_entry[e].set(C)
        return None
    
    # a fallback log method
    def log(self,level,text):
        print "LOG("+str(level)+"): "+ text
