from decimal import Decimal

from loguru import logger

from rosreestrXml.ui.tools.db_helper.dbRsc import DbRsc


#from PanoramaRsc.ui.add_tools.helper_db.dbRsc import DbRsc


def ExistTable(db,name_table):
    sql="select name from sqlite_master where type='table' and name='"+name_table+"'"
    rows=db.select(sql)
    if len(rows)==0:
        return False
    return True
def createFkKeyName(name_tab):
    return "fk_" +name_tab.lower()


def createTable(db,object_db,parent_table_name=None,dictionary_tables=None):
    print("Create Table:"+object_db['name'])

    sql_create="Create Table "+object_db['name']+" ("
    for field in object_db['fields']:
        #sql_create=sql_create+field['name']
        sql_field=field['name']
        if field['name']=='row_id':
            #sql_field=sql_field+" UNIQUEIDENTIFIER PRIMARY KEY "
            sql_field = sql_field + " INTEGER PRIMARY KEY "
            sql_create=sql_create+sql_field
            continue
        if parent_table_name is not None and field['name']=='parent_row_id':
            sql_field = sql_field + "  INTEGER REFERENCES "+parent_table_name+"([row_id]) "
            sql_create = sql_create +" , " +sql_field
            continue
        sql_field=","+field['name']+" "+field['type']
        sql_create = sql_create + sql_field
    if dictionary_tables is not None:
        for tab_dict in dictionary_tables:
            #name_fk_key="fk_"+tab_dict['name'].lower()
            name_fk_key=createFkKeyName(tab_dict['name'])
            sql_field = name_fk_key + "  INTEGER REFERENCES " + tab_dict['name'] + "([row_id]) "
            sql_create = sql_create + " , " + sql_field
    sql_create=sql_create+")"
    isok=db.runSqlNoResult(sql_create)
    return
class XmlDbStruct:
    def __init__(self,db:DbRsc,function_call_bak):
        self.__duble_table_name={}
        self.__db=db
        self.__function_progressBar=function_call_bak

    def dataFromXmlObj(self,obj_db, parent_table=None):
        self.__function_progressBar()
        min_count_fielda = 2
        if parent_table is None:
            min_count_fielda = min_count_fielda - 1
        count_fields = len(obj_db['fields'])
        if obj_db['name'] == 'common_data' or obj_db['name'] == 'land_record':
            jkl = 0
        list_dict_link = []
        existDict = False
        for child_table in obj_db['children_table']:
            if child_table['type_obj'] == 'Dict':
                list_dict_link.append(child_table)
                existDict = True

        if existDict:

            self.__createDictionaryTable(list_dict_link)
        else:
            list_dict_link=None
        if count_fields > min_count_fielda:
            ''' возможно создаем таблицу '''

            is_exist=ExistTable(self.__db,obj_db['name'])

            if is_exist:
                if not (obj_db['name'] in self.__duble_table_name.keys()):
                    #self.__duble_table_name.append(obj_db['name'])
                    self.__duble_table_name[obj_db['name']]=[]

                self.__duble_table_name[obj_db['name']].append(parent_table)

            if len(obj_db['children_table']) == 0:
                ''' '''
                createTable(self.__db, obj_db, parent_table,list_dict_link)
                return
            ''' create table '''

            createTable(self.__db, obj_db, parent_table,list_dict_link)
        ''' Проверяем есть ли дочерние справочники'''
        '''
        list_dict_link=[]
        for child_table in obj_db['children_table']:
            if child_table['type_obj'] == 'Dict':
                list_dict_link.append(child_table['name'])
        existDict=False
        if len(list_dict_link)>0:
            existDict=True
        '''
        for child_table in obj_db['children_table']:

            if child_table['type_obj'] == 'Dict':
                ''' Cылка на справочник'''
                continue
            if min_count_fielda == 2 and len(child_table['children_table']) == 0:

                self.dataFromXmlObj(child_table, parent_table)
                continue
            if count_fields == 2:
                '''
                jkl=0
                for next_childern in child_table['children_table']:
                    dataFromXmlObj(next_childern, db, obj_db['name'])
                '''
                self.dataFromXmlObj(child_table,  parent_table)
            else:
                self.dataFromXmlObj(child_table,  obj_db['name'])
            jkl = 0
        jkl = 0

    @property
    def DubleTbaleNames(self):
        return self.__duble_table_name

    def __createDictionaryTable(self,dictuionary_tab_obj):
        for obj_dict_tab in dictuionary_tab_obj:
            is_exist = ExistTable(self.__db, obj_dict_tab['name'])
            if is_exist:
                continue
            ''' создаем справочник'''
            fields=[]
            for fld in obj_dict_tab['fields']:
                if fld=='parent_row_id':
                    continue
                fields.append(fld)
            obj_dict_tab['fields']=fields
            createTable(self.__db,obj_dict_tab)
    def __xmlToDb(self,json_obj,xml_obj,parent_id=None):
        self.__function_progressBar()
        type_obj=json_obj['type_obj']
        if json_obj['name'].find( 'contour')>=0:
            jkl=0
        count_fields=len(json_obj['fields'])
        lim_fields=2
        if parent_id is None:
            lim_fields=1
        values_fields = []
        name_out = []
        for child_tab in json_obj['children_table']:
            if child_tab['type_obj']=='Dict':
                ''' ссылка на справочник '''
                name_property=child_tab['name']
                if name_property=='type':
                    name_property=name_property+"_"
                if isinstance(xml_obj,list):
                    for xml_item in xml_obj:
                        xml_obj_dictionary = getAttClass(xml_item, name_property)
                        fk_key = self.__saveDictionaryValues(child_tab, xml_obj_dictionary)
                        name_fk_key = createFkKeyName(child_tab['name'])
                        values_fields.append(fk_key)
                        name_out.append(name_fk_key)
                else:
                    xml_obj_dictionary=getAttClass(xml_obj,name_property)
                    if xml_obj_dictionary is not None:
                        fk_key=self.__saveDictionaryValues(child_tab,xml_obj_dictionary)
                        name_fk_key=createFkKeyName(child_tab['name'])
                        values_fields.append(fk_key)
                        name_out.append(name_fk_key)
                jkl=0

        if count_fields>lim_fields:

            ''' Создаем таблицу и читает дополнительные поля'''
            if isinstance(xml_obj, list):
                for xml_item in xml_obj:
                    row_id_base = self.__saveTable(json_obj, xml_item, lim_fields, parent_id, name_out, values_fields)
            else:
                row_id_base=self.__saveTable(json_obj,xml_obj,lim_fields,parent_id,name_out,values_fields)
            #values_fields=[]
            '''
            fields_name=json_obj['fields']
            #name_out=[]
            if parent_id is not None:
                name_out.append("parent_row_id")
                values_fields.append(parent_id)

            for i in range(lim_fields,count_fields):
                name_field=fields_name[i]['name']
                if name_field == 'row_id' or name_field == 'parent_row_id':
                    continue
                if isinstance(xml_obj,list):
                    for xml_item in xml_obj:
                        property_name = getAttClass(xml_item, name_field)
                        jkl=0

                property_name=getAttClass(xml_obj,name_field)
                if property_name is not None:
                    name_out.append(name_field)
                    values_fields.append(property_name)
            sql_insert="Insert Into "+json_obj['name']+" ("+",".join(name_out)+") "
            sql_insert=sql_insert+" VALUES ("+",".join(['?']*len(name_out))+")"

            row_id_base=self.__db.insertGetAutoinriment(sql_insert,tuple(values_fields))
            '''
            if len(json_obj['children_table']) == 0:
                return
        if len(json_obj['fields'])==lim_fields:
            row_id_base=parent_id
        #att_method=getattr(xml_obj, type_obj)
        #values=att_method()
        for child_table in json_obj['children_table']:
            type_obj=child_table['type_obj']
            if type_obj=='Dict':
                continue
            if type_obj=="None":
                jkl=0

            type_obj=child_table['name']
            if type_obj=='type':
                ''' type служебное'''
                type_obj=type_obj+"_"
            if isinstance(xml_obj,list):
                for xml_item in xml_obj:
                    xml_obj_children = getAttClass(xml_item, type_obj)
                    if xml_obj_children is None:
                        continue
                    # if len(child_table['fields'])==lim_fields:

                    self.__xmlToDb(child_table, xml_obj_children, row_id_base)
            else:
                xml_obj_children=getAttClass(xml_obj,type_obj)
                if xml_obj_children is None:
                    continue
                #if len(child_table['fields'])==lim_fields:

                self.__xmlToDb(child_table,xml_obj_children,row_id_base)



            jkl=0
    def loadToDb(self,json_obj,xml_obj):
        self.__xmlToDb(json_obj,xml_obj)
    def __saveDictionaryValues(self,json_obj,xml_obj):
        name_fields=[]
        values=[]
        for field in json_obj['fields']:
            name_field = field ['name']
            if name_field=='row_id' or name_field=='parent_row_id':
                continue
            property_name = getAttClass(xml_obj, name_field)
            if property_name is not None:
                name_fields.append(name_field)
                values.append(property_name)
        sql_insert = "Insert Into " + json_obj['name'] + " (" + ",".join(name_fields) + ") "
        sql_insert = sql_insert + " VALUES (" + ",".join(['?'] * len(name_fields)) + ")"

        row_id_base = self.__db.insertGetAutoinriment(sql_insert, tuple(values))
        return row_id_base
    def __saveTable(self,json_obj,xml_obj,lim_fields,parent_id,add_name=None,add_value=None):

        name_out=[]
        values_fields=[]
        if add_name is not None:
            name_out.extend(add_name)
            values_fields.extend(add_value)
        fields_name = json_obj['fields']
        # name_out=[]
        if parent_id is not None:
            name_out.append("parent_row_id")
            values_fields.append(parent_id)
        count_fields = len(fields_name)
        for i in range(lim_fields, count_fields):
            name_field = fields_name[i]['name']
            if name_field == 'row_id' or name_field == 'parent_row_id':
                continue


            property_name = getAttClass(xml_obj, name_field)
            if property_name is not None:
                name_out.append(name_field)
                if isinstance(property_name,Decimal):
                    property_name=float(property_name)
                values_fields.append(property_name)
        sql_insert = "Insert Into " + json_obj['name'] + " (" + ",".join(name_out) + ") "
        sql_insert = sql_insert + " VALUES (" + ",".join(['?'] * len(name_out)) + ")"

        row_id_base = self.__db.insertGetAutoinriment(sql_insert, tuple(values_fields))
        if row_id_base is None:
            jkl=0
        return row_id_base
def getAttClass(base_cls,name):
    att=None
    try:
        att=getattr(base_cls, name)
    except:
        logger.exception("not find property:"+name+" in "+str(base_cls))
        return None
    return att

