
import traceback
from BaseDataMaintenance.common.Utils import log
from datetime import datetime

class BaseModel():

    def __init__(self):
        raise NotImplementedError()

    def getPrimary_keys(self):
        raise NotImplementedError()

    def getProperties(self):
        return self.__dict__

    def getProperties_ots(self):
        new_dict = {}
        for k,v in self.__dict__.items():
            if k in self.columns:
                if v is not None:
                    if isinstance(v,(str,int,float)):
                        pass
                    elif isinstance(v,(datetime)):
                        v = v.strftime("%Y-%m-%d %H:%M:%S")
                    else:
                        v = str(v)
                    new_dict[k] = v
        return new_dict

    def setValue(self,k,v,isColumn=False):
        if "all_columns" not in self.__dict__:
            self.all_columns = []
        self.__dict__[k] = v
        if isColumn:
            if k not in (set(self.all_columns)):
                self.all_columns.append(k)

    def insert_row(self,pool,retrys=2):
        for i in range(retrys):
            try:
                conn = pool.getConnector()
                cursor = conn.cursor()
                sql = "insert into %s"%(self.table_name)
                s_columns = "("
                s_values = "values("
                _set_columns = set(self.all_columns)
                for k,v in self.__dict__.items():
                    if k in _set_columns:
                        if v is not None and str(v)!="":
                            s_columns += "%s,"%k
                            if isinstance(v,str):
                                s_values += " E'%s',"%v
                            else:
                                s_values += "%d,"%v
                s_columns = "%s)"%s_columns[:-1]
                s_values = "%s)"%s_values[:-1]
                sql = "%s%s%s"%(sql,s_columns,s_values)
                cursor.execute(sql)
                conn.commit()

                pool.putConnector(conn)
                return
            except Exception as e:
                conn.close()
                log("insert error with time:%d"%i)
                traceback.print_exc()



    def update_row(self,pool):
        conn = pool.getConnector()
        try:
            cursor = conn.cursor()
            sql = "update %s set "%(self.table_name)
            s_columns = ""
            s_where = " where 1=1 "
            _set_columns = set(self.all_columns)
            _set_keys = set(self.getPrimary_keys())
            has_key = False
            for k,v in self.__dict__.items():
                if k in self.columns and k not in _set_keys:
                    if v is not None and str(v)!="":
                        s_columns += "%s="%k
                        if isinstance(v,str):
                            s_columns += "E'%s',"%v
                        else:
                            s_columns += "%d,"%v
                elif k in _set_keys:
                    if v is None or str(v)=="":
                        raise RuntimeError("主键%s为空"%k)
                    s_where += " and %s="%k
                    if isinstance(v,str):
                        s_where += "E'%s' "%v
                    else:
                        s_where += "%d "%v
                    has_key = True
            s_columns = "%s"%s_columns[:-1]
            sql = "%s%s%s"%(sql,s_columns,s_where)
            # log("update attachment:%s"%(sql))
            if has_key:
                update_rows = cursor.execute(sql)
                conn.commit()
                return update_rows
        except Exception as e:
            traceback.print_exc()
            conn.rollback()
        finally:
            pool.putConnector(conn)
        return 0

    def exists(self,pool_postgres):
        try:
            conn = pool_postgres.getConnector()
            s_where = " where 1=1 "
            _set_columns = set(self.all_columns)
            _set_keys = set(self.getPrimary_keys())
            for k,v in self.__dict__.items():
                if k in _set_keys:
                    if v is None or str(v)=="":
                        raise RuntimeError("主键%s为空"%k)
                    s_where += " and %s="%k
                    if isinstance(v,str):
                        s_where += "'%s' "%v
                    else:
                        s_where += "%d "%v
            cursor = conn.cursor()
            sql = "select count(1) from %s %s"%(self.table_name,s_where)
            cursor.execute(sql)
            rows = cursor.fetchall()
            pool_postgres.putConnector(conn)
            if rows[0][0]==0:
                return False
            return True
        except Exception as e:
            conn.close()
            traceback.print_exc()

    @staticmethod
    def select_rows(conn,cls,table_name,conditions,rows_to_get="*",limit=None):
        list_result = []
        s_limit = ""
        if limit is not None:
            s_limit = "limit %d"%limit
        if len(conditions)>0:
            s_where = " where %s"%(" and ".join(conditions))
        else:
            s_where = ""

        cursor = conn.cursor()
        sql = "select %s from %s %s %s"%(rows_to_get,table_name,s_where,s_limit)
        log("select rows:%s"%(sql))
        cursor.execute(sql)

        vol = cursor.description
        rows = cursor.fetchall()
        for row in rows:
            _dict = {}
            for _vol,_val in zip(vol,row):
                _name = _vol[0]
                _dict[_name] = _val
            list_result.append(cls(_dict))
        return list_result



