import os

from PySide2.QtCore import QObject, Signal
import time
import xml.etree.ElementTree as ET
from lxml import etree
from pathlib import Path, PurePath

from axipy.app import Notifications

from .addTools.tabFiles import FileSourceMws, factorySource, FileSource


def getFileNameLxml(node,namespace)->str:
    node_file_name=node.xpath('mxp:FileName',namespaces=namespace)
    if node_file_name is None:
        return None,None
    id = node.attrib['id']
    filename=None
    try:
        filename=node_file_name[0].text
    except:
        pass
    if filename is None:
        try:
            filename = node_file_name.text
        except:
            return None,None,None

    dataPrividerName = node.attrib['providerId']
    #filename = node_file_name.text
    return filename, id, dataPrividerName

def getFileName(node)->str:
    node_file_name=node.find('{http://www.mapinfo.com/mxp}FileName')
    if node_file_name is None:
        return None,None
    id = node.attrib['id']
    dataPrividerName=node.attrib['providerId']
    filename=node_file_name.text
    return filename,id,dataPrividerName
def getListTabInMwsLxml(tree_nodes,path_folder_mws,namespaces):
    list_tab_in_wms=[]
    #nodes_TABFileDataSourceDefinition = tree_nodes.xpath('//mxp:WorkSpace/mxp:DataSourceDefinitionSet/mxp:TABFileDataSourceDefinition/*',namespaces=namespaces)
    nodes_TABFileDataSourceDefinition = tree_nodes.xpath(
        '//mxp:WorkSpace/mxp:DataSourceDefinitionSet/*', namespaces=namespaces)
    #    '//mxpDataSourceDefinitionSet/{http://www.mapinfo.com/mxp}TABFileDataSourceDefinition')
    for node in nodes_TABFileDataSourceDefinition:

        file_name,id,nameProvider = getFileNameLxml(node,namespaces)
        if file_name is None:
            continue
        file_source=FileSourceMws(file_name,id)
        full_path = str(path_folder_mws.joinpath(file_name))
        abs_path = PurePath(full_path)
        file_source.setParentFolder(path_folder_mws)
        list_tab_in_wms.append({'source': file_source, 'provider': nameProvider})
        #list_tab_in_wms.append(file_source)
    return list_tab_in_wms

def getListTabInMws(tree_nodes,path_folder_mws):
    list_tab_in_wms=[]
    nodes_TABFileDataSourceDefinition = tree_nodes.findall(
        '/{http://www.mapinfo.com/mxp}DataSourceDefinitionSet/{http://www.mapinfo.com/mxp}TABFileDataSourceDefinition')
    for node in nodes_TABFileDataSourceDefinition:
        file_name,id = getFileName(node)
        file_source=FileSourceMws(file_name,id)
        #full_path = str(path_folder_mws.joinpath(file_name))
        #abs_path = PurePath(full_path)
        file_source.setParentFolder(path_folder_mws)
        list_tab_in_wms.append(file_source)
    nodes_TABFileDataSourceDefinition = tree_nodes.findall(
        '/{http://www.mapinfo.com/mxp}DataSourceDefinitionSet/{http://www.mapinfo.com/mxp}RasterFileDataSourceDefinition')
    for node in nodes_TABFileDataSourceDefinition:
        file_name, id, nameProvider = getFileName(node)
        file_source = FileSourceMws(file_name, id)
        # full_path = str(path_folder_mws.joinpath(file_name))
        # abs_path = PurePath(full_path)
        file_source.setParentFolder(path_folder_mws)
        list_tab_in_wms.append({'source': file_source, 'provider': nameProvider})
    return list_tab_in_wms
def updateMwsLxml(tree_nodes,listTabUpdate,path_folder_dest,namespaces):
    nodes_TABFileDataSourceDefinition = tree_nodes.xpath(
        '//mxp:WorkSpace/mxp:DataSourceDefinitionSet/mxp:TABFileDataSourceDefinition', namespaces=namespaces)
    for node in nodes_TABFileDataSourceDefinition:
        id = node.attrib['id']
        items_list=list(filter(lambda tab_mws:  tab_mws['source'].idSource ==id,listTabUpdate ))
        if len(items_list)==0:
            print("Not find ID:"+id)
            continue
        #node_file_name = node.find('{http://www.mapinfo.com/mxp}FileName')
        node_file_name = node.xpath('mxp:FileName',namespaces=namespaces)

        relative_path=os.path.relpath(items_list[0]['source'].destPath,path_folder_dest)
        node_file_name[0].text=relative_path
    nodes_TABFileDataSourceDefinition = tree_nodes.findall(
        '/{http://www.mapinfo.com/mxp}DataSourceDefinitionSet/{http://www.mapinfo.com/mxp}RasterFileDataSourceDefinition')
    for node in nodes_TABFileDataSourceDefinition:
        id = node.attrib['id']
        items_list = list(filter(lambda tab_mws: tab_mws['source'].idSource == id, listTabUpdate))
        if len(items_list) == 0:
            print("Not find ID:" + id)
            continue
        node_file_name = node.find('{http://www.mapinfo.com/mxp}FileName')
        relative_path = os.path.relpath(items_list[0]['source'].destPath, path_folder_dest)
        node_file_name.text = relative_path
def updateMws(tree_nodes,listTabUpdate,path_folder_dest):
    nodes_TABFileDataSourceDefinition = tree_nodes.findall(
        '/{http://www.mapinfo.com/mxp}DataSourceDefinitionSet/{http://www.mapinfo.com/mxp}TABFileDataSourceDefinition')
    for node in nodes_TABFileDataSourceDefinition:
        id = node.attrib['id']
        items_list=list(filter(lambda tab_mws:  tab_mws.idSource ==id,listTabUpdate ))
        if len(items_list)==0:
            print("Not find ID:"+id)
            continue
        node_file_name = node.find('{http://www.mapinfo.com/mxp}FileName')
        relative_path=os.path.relpath(items_list[0].destPath,path_folder_dest)
        node_file_name.text=relative_path
class ProcessCopyMws(QObject):
    updateProcess = Signal(float)
    updateFormatProgressBar = Signal(str)
    finished = Signal(int)

    def __init__(self, name_prosess, parent_class):
        self.__name_process = name_prosess

        super(ProcessCopyMws, self).__init__()
        self.__parent = parent_class
        self.__erorr_message = None
    def setParams(self,params):
        self.__params=params
    def __isCancel(self):
        self.__cancelProcess=True
    def setCancel(self):
        self.__cancelProcess=True
    def __process_callback(self,complete, message=None, user_data=None):
        #print('progress: {}, message: "{}", unknown {}'.format(complete, message,user_data))
        if self.__cancelProcess:
            return 0
        self.updateProcess.emit(complete*100)
        time.sleep(0.001)
        #logging.debug(" update progress bar "+str(complete*100))
        #self.__parent.window.pr_bar.setValue(complete*100)
        #print(complete*100)
        return 1

    def __copyTabSourceOld(self,list_tab_source, path_dest: Path, folder_for_tab='table'):
        path_dest_for_tab = path_dest.joinpath(folder_for_tab)
        '''
        if not path_dest_for_tab.exists():
            path_dest_for_tab.mkdir()
        '''
        geometry_filter=self.__params['geometry_filter']
        for i,tab_source in enumerate(list_tab_source):
            is_cancel = self.__process_callback(i / len(list_tab_source))
            if is_cancel == 0:
                # logging.debug(("send send cancel"))
                break
            cslSource = factorySource(tab_source)
            if len(tab_source.subfolders) == 0:
                if not path_dest_for_tab.exists():
                    path_dest_for_tab.mkdir()
                cslSource.copy(path_dest_for_tab,geometry_filter)
            else:
                cslSource.copy(path_dest,geometry_filter)
            tab_source.setDestPath(cslSource.destPath)

    def __copyTabSource(self, list_tab_source, path_dest: Path, folder_for_tab='table'):
        path_dest_for_tab = path_dest.joinpath(folder_for_tab)
        spatial_filter=self._ProcessCopyMws__params['geometry_filter']
        '''
        if not path_dest_for_tab.exists():
            path_dest_for_tab.mkdir()
        '''
        for i,tab_source_item in enumerate(list_tab_source):
            is_cancel = self.__process_callback((i+1) / len(list_tab_source))
            if is_cancel == 0:
                # logging.debug(("send send cancel"))
                break
            tab_source = tab_source_item['source']
            if tab_source_item['source'].idSource=='id22':
                jkl=0

            cslSource = factorySource(tab_source_item)
            if cslSource is None:
                return
            if isinstance(cslSource, FileSource):
                path_dest_for_tab = path_dest.joinpath("any_data")
            if len(tab_source.subfolders) == 0:
                if not path_dest_for_tab.exists():
                    path_dest_for_tab.mkdir()
                cslSource.copy(path_dest_for_tab,spatial_filter)
            else:
                if not (tab_source.subfolders[0] == 'table' or tab_source.subfolders[0] == 'any_data'):
                    new_path_dest = path_dest.joinpath(tab_source.subfolders[0])
                    cslSource.copy(new_path_dest,spatial_filter)
                else:
                    if not path_dest_for_tab.exists():
                        path_dest_for_tab.mkdir()
                    cslSource.copy(path_dest_for_tab,spatial_filter)
                # cslSource.copy(new_path_dest)
            tab_source.setDestPath(cslSource.destPath)

    def run(self):
        try:
            self.__parent.disconnect(self.__isCancel)
        except:
            pass
        self.__parent.cancelProcess.connect(self.__isCancel)
        self.__cancelProcess=False
        path_source_mws=self.__params['source']
        path_destination_mws=self.__params['dest']
        ''' Читаем исходный mws'''
        self.updateFormatProgressBar.emit("Чтение рабочего набора .. %p%")
        self.updateProcess.emit(0)
        '''
        tree = ET.parse(path_source_mws)
        root = tree.getroot()
        '''

        ''' Всех таблиц в mws '''
        try:
            tree = etree.parse(path_source_mws)
        except:
            self.updateProcess.emit(0)
            self.finished.emit(0)
            Notifications.push('Копирование mws', 'Файл '+path_source_mws+' не является mws', Notifications.Critical)
            return
        ns1 = {"gml": "http://www.opengis.net/gml", "mxp": "http://www.mapinfo.com/mxp"}
        #list_tab = getListTabInMws(tree, Path(path_source_mws).parent)
        list_tab = getListTabInMwsLxml(tree, Path(path_source_mws).parent,ns1)
        if len(list_tab)==0:
            self.updateProcess.emit(0)
            self.finished.emit(0)
            Notifications.push('Копирование mws', 'Файл ' + path_source_mws + ' не сожержит таблиц',
                               Notifications.Critical)
            return

        dest_folder = Path(path_destination_mws).parent
        if not dest_folder.exists():
            dest_folder.mkdir()
        self.updateFormatProgressBar.emit("Копирование данных mws .. %p%")
        self.__copyTabSource(list_tab,dest_folder)
        if self.__cancelProcess:
            self.updateProcess.emit(0)
            self.finished.emit(0)
            Notifications.push('Копирование mws', 'Было преррвано', Notifications.Information)
            return
        #updateMws(tree, list_tab, str(dest_folder))
        updateMwsLxml(tree, list_tab, str(dest_folder),ns1)
        '''
        text_mws = str(ET.tostring(root, encoding='utf-8'), 'UTF-8')
        text_mws=text_mws.replace('xmlns:ns0','xmlns:mxp')
        text_mws = text_mws.replace('xmlns:ns1', ' xmlns:gml')
        text_mws = text_mws.replace('ns0:', '')
        # text_mws=text_mws.replace('ns1:Point','ml:Point')
        text_mws = text_mws.replace('ns1:', 'gml:')
        # text_mws=text_mws.replace('gml:','')
        text_mws = '<?xml version="1.0" encoding="UTF-8"?>' + text_mws
        '''
        '''
        with open(pathOut_mws, 'wb') as f:
            tree.write(f, encoding='utf-8')
        
        with open(path_destination_mws, "w", encoding="utf-8") as mws_file:
            mws_file.write(text_mws)
        '''
        et = etree.ElementTree(tree.getroot())
        et.write(path_destination_mws, pretty_print=True, xml_declaration=True, encoding='UTF-8')
        Notifications.push('Копирование mws', 'Выполнено', Notifications.Success)
        self.updateProcess.emit(0)
        self.finished.emit(100)




