import os

import axipy
from PySide2 import QtCore
from PySide2.QtCore import QFile
from PySide2.QtGui import QDoubleValidator
from PySide2.QtUiTools import QUiLoader
from axipy import AreaUnit, AreaUnits

from .Utils import readPropertyes, saveProperties


class TopoTools:
    __curent_area_unit_lim=None
    __def_style_symbol='Symbol(67, 16711680, 24)'
    __def_style_symbol_db='Symbol (66,65280,24,"MapInfo Symbols",0,0) '
    __def_style_symbol_angle='Symbol (65,65280,24,"MapInfo Symbols",0,0) '
    __def_style_area_intersect="Pen (1, 2, 0) Brush (48, 16776960, 16711680)"
    __def_style_area_lim="Pen (1, 2, 0) Brush (48, 16776960, 16711680)"
    __def_style_gap='Pen (2, 2, 16711680) Brush (84, 16711680, 16776960)'
    __style_symbol=None
    __style_db_point=None
    __style_area_intersect=None
    __style_area_gap=None
    __name_plugin = 'TopoPolygon'
    __name_file_plugin_proporties = 'topoPolygon_properties.json'
    __statusIsOk=False
    def __init__(self):
        self.__parentWin=axipy.app.mainwindow.qt_object()
        self.load_ui()
        self.__readInitStyle()
        self.__initButtomStyleDef()
        self.__widgetStyle()
        self.__initTableList()
        db_validator=QDoubleValidator()
        db_validator.setBottom(0.0)
        angle_validator=QDoubleValidator(0.0,180,2)
        #angle_validator.setBottom(0.0,180,2)
        self.window.ln_e_area_max.setValidator(db_validator)
        self.window.ln_e_area_min.setValidator(db_validator)
        self.window.ln_lim_angle.setValidator(angle_validator)
        self.window.pbClose.clicked.connect(self.__close)
        self.window.pb_run.clicked.connect(self.__run)
        self.window.ch_self_intersect.stateChanged.connect(self.__ch_intersect)
        self.window.ch_poly_intersect.stateChanged.connect(self.__area_intersect)
        self.window.ch_lim_angle.stateChanged.connect(self.__ch_lim_angle)
        self.window.ch_gap_polygon.stateChanged.connect(self.__gap_area_intersect)
        self.window.ch_db_point.stateChanged.connect(self.__ch_dp_points)
        self.window.ch_area_polygon.stateChanged.connect(self.__ch_area_limit)
        self.window.cb_AreaUnits_lim.currentIndexChanged.connect(self.__ch_units_lim)
        self.__init_AreaUnits()
    def load_ui(self):
        loader = QUiLoader()
        #path = os.path.join(os.path.dirname(__file__), "DlgSimpleTopoExtDbPointAreaPt.ui")
        path = os.path.join(os.path.dirname(__file__), "DlgSimpleTopoExtDbPointAreaPtX1.ui")
        ui_file = QFile(path)
        ui_file.open(QFile.ReadOnly)
        self.window  = loader.load(ui_file,self.__parentWin)
        ui_file.close()
        #self.window.setWindowModality(QtCore.Qt.ApplicationModal)
        self.window.setWindowFlags(
            self.window.windowFlags() & ~QtCore.Qt.WindowCloseButtonHint & ~QtCore.Qt.WindowContextHelpButtonHint)
    def show(self):
        self.window.exec()
    @property
    def PropertyesForCheckTopology(self):
        if not self.__statusIsOk:
            return None
        propertyes_topo={}
        double_points={}
        double_points['style']=self.__style_db_point.to_mapinfo()
        double_points['enable']=self.window.ch_db_point.isChecked()
        propertyes_topo['double_points']=double_points
        self_intersect={}
        self_intersect['style']=self.__style_symbol.to_mapinfo()
        self_intersect['enable']=self.window.ch_self_intersect.isChecked()
        propertyes_topo['self_intersect']=self_intersect
        area_intersect={}
        area_intersect['style']=self.__style_area_intersect.to_mapinfo()
        area_intersect['enable']=self.window.ch_poly_intersect.isChecked()
        propertyes_topo['area_intersect']=area_intersect
        angle_lim={}
        angle_lim['enable']=self.window.ch_lim_angle.isChecked()
        angle_lim['style']=self.__style_angle_lim.to_mapinfo()
        angle_lim['angle_limit']=float(self.window.ln_lim_angle.text())
        propertyes_topo['angle_limit']=angle_lim
        gap_area={}
        gap_area['style']=self.__style_area_gap.to_mapinfo()
        gap_area['enable']=self.window.ch_gap_polygon.isChecked()
        gap_area['area_limmit']=float(self.window.ln_e_area_max.text())
        area_limits_in_sq_km=self.__getSelectUnitToSqKm(float(self.window.ln_e_area_max.text()))
        gap_area['area_limmit']=area_limits_in_sq_km
        propertyes_topo['gap_area']=gap_area
        lim_area_polygon={}
        lim_area_polygon['enable']=self.window.ch_area_polygon.isChecked()
        lim_area_polygon['style']=self.__style_area_lim.to_mapinfo()
        lim_area_polygon['area_limit']=self.__getSelectUnitToSqKmFrom(float(self.window.ln_e_area_min.text()),self.__curent_area_unit_lim)
        propertyes_topo['area_limit']=lim_area_polygon
        propertyes_topo['table_source']=self.window.cb_source_table.currentText()
        return propertyes_topo
    def __close(self):
        self.__statusIsOk=False
        self.window.close()
    def __run(self):
        self.__statusIsOk=True
        self.__style_symbol=self.__pb_style_intesect.style
        self.__style_area_intersect=self.__pb_style_area_intesect.style
        self.__style_area_gap=self.__pb_style_area_gap.style
        self.__style_db_point=self.__pb_style_db_point.style
        self.__style_area_lim=self.__pb_style_area_lim.style
        self.__style_angle_lim=self.__pb_style_lim_angle.style
        self.__writeIniStyle()
        self.window.close()
    def __ch_intersect(self):
        self.__pb_style_intesect.setEnabled(self.window.ch_self_intersect.isChecked())

        self.__setEnableRun()
    def __ch_dp_points(self):
        self.__pb_style_db_point.setEnabled(self.window.ch_db_point.isChecked())

        self.__setEnableRun()
    def __ch_area_limit(self):
        self.__pb_style_area_lim.setEnabled(self.window.ch_area_polygon.isChecked())
        self.window.gb_area_limit.setEnabled(self.window.ch_area_polygon.isChecked())
        self.__setEnableRun()
    def __area_intersect(self):
        self.__pb_style_area_intesect.setEnabled(self.window.ch_poly_intersect.isChecked())

        self.__setEnableRun()
    def __ch_lim_angle(self):
        self.__pb_style_lim_angle.setEnabled(self.window.ch_lim_angle.isChecked())
        self.window.gb_angle_lim.setEnabled(self.window.ch_lim_angle.isChecked())
        self.__setEnableRun()
    def __gap_area_intersect(self):
        self.__pb_style_area_gap.setEnabled(self.window.ch_gap_polygon.isChecked())
        self.window.groupBox_gap_area.setEnabled(self.window.ch_gap_polygon.isChecked())
        #self.window.gb_area_limit.setEnabled(self.window.ch_area_polygon.isChecked())
        self.__setEnableRun()
    def __ch_units_lim(self):
        name_area_unit=self.window.cb_AreaUnits_lim.currentText()
        if self.__curent_area_unit_lim is None:
            self.__curent_area_unit_lim=name_area_unit
            return
        cur_unit_lim_area=float(self.window.ln_e_area_min.text())
        old_name_unit_area=self.__curent_area_unit_lim

        self.__curent_area_unit_lim=name_area_unit
        old_unit_area=self.__find_area_unit(old_name_unit_area)
        cur_unit_area=self.__find_area_unit(name_area_unit)
        new_val_area_coef=old_unit_area.to_unit(cur_unit_area)
        new_val_area=cur_unit_lim_area*new_val_area_coef
        self.window.ln_e_area_min.setText(str(new_val_area))
        jkl=0
    @property
    def isOk(self):
        return self.__statusIsOk
    def __writeIniStyle(self):
        property_plugins={}
        property_plugins['double_point']=self.__style_db_point.to_mapinfo()
        property_plugins['intersect_point']=self.__style_symbol.to_mapinfo()
        property_plugins['area_intersect']=self.__style_area_intersect.to_mapinfo()
        property_plugins['area_gap']=self.__style_area_gap.to_mapinfo()
        property_plugins['area_lim']=self.__style_area_lim.to_mapinfo()
        property_plugins['angle_lim']=self.__style_angle_lim.to_mapinfo()
        saveProperties(self.__name_plugin,self.__name_file_plugin_proporties,property_plugins)
    def __readInitStyle(self):
        try:
            obj_property=readPropertyes(self.__name_plugin,self.__name_file_plugin_proporties)
        except:
            obj_property=None
        if obj_property is None:
            self.__style_symbol=axipy.Style.from_mapinfo(self.__def_style_symbol)
            self.__style_area_intersect=axipy.Style.from_mapinfo(self.__def_style_area_intersect)
            self.__style_area_gap = axipy.Style.from_mapinfo(self.__def_style_gap)
            self.__style_db_point=axipy.Style.from_mapinfo(self.__def_style_symbol_db)
            self.__style_area_lim=axipy.Style.from_mapinfo(self.__def_style_area_lim)
            self.__style_angle_lim=axipy.Style.from_mapinfo(self.__def_style_symbol_angle)
        else:
            self.__style_db_point=axipy.Style.from_mapinfo(obj_property['double_point'])
            self.__style_symbol = axipy.Style.from_mapinfo(obj_property['intersect_point'])
            self.__style_area_intersect = axipy.Style.from_mapinfo(obj_property['area_intersect'])
            self.__style_area_gap = axipy.Style.from_mapinfo(obj_property['area_gap'])
            self.__style_area_lim=axipy.Style.from_mapinfo(obj_property['area_lim'])
            self.__style_angle_lim=axipy.Style.from_mapinfo(obj_property['angle_lim'])

    def __initButtomStyleDef(self):
        #self.__styleSymIntersect = axipy.Style.from_mapinfo("Symbol(67, 16711680, 24)")
        self.__pb_style_db_point = axipy.StyleButton(self.__style_db_point, self.window)
        self.__pb_style_db_point.setFixedHeight(40)
        self.__pb_style_db_point.setFixedWidth(40)
        self.__pb_style_db_point.setEnabled(False)

        self.__pb_style_intesect = axipy.StyleButton(self.__style_symbol, self.window)
        self.__pb_style_intesect.setFixedHeight(40)
        self.__pb_style_intesect.setFixedWidth(40)
        self.__pb_style_intesect.setEnabled(False)

        self.__pb_style_lim_angle = axipy.StyleButton(self.__style_angle_lim, self.window)
        self.__pb_style_lim_angle.setFixedHeight(40)
        self.__pb_style_lim_angle.setFixedWidth(40)
        self.__pb_style_lim_angle.setEnabled(False)

        self.__pb_style_area_intesect = axipy.StyleButton(self.__style_area_intersect, self.window)
        self.__pb_style_area_intesect.setFixedHeight(40)
        self.__pb_style_area_intesect.setFixedWidth(40)
        self.__pb_style_area_intesect.setEnabled(False)

        self.__pb_style_area_lim= axipy.StyleButton(self.__style_area_lim, self.window)
        self.__pb_style_area_lim.setFixedHeight(40)
        self.__pb_style_area_lim.setFixedWidth(40)
        self.__pb_style_area_lim.setEnabled(False)

        self.__pb_style_area_gap= axipy.StyleButton(self.__style_area_gap, self.window)
        self.__pb_style_area_gap.setFixedHeight(40)
        self.__pb_style_area_gap.setFixedWidth(40)
        self.__pb_style_area_gap.setEnabled(False)
    def __setEnableRun(self):
        if self.__pb_style_db_point.isEnabled() or self.__pb_style_intesect.isEnabled() or self.__pb_style_area_intesect.isEnabled() or self.__pb_style_area_lim.isEnabled() or self.__pb_style_area_gap.isEnabled() or self.__pb_style_lim_angle.isEnabled():
            self.window.pb_run.setEnabled(True)
        else:
            self.window.pb_run.setEnabled(False)
    def __widgetStyle(self):
        self.window.wg_style_db_point.addWidget(self.__pb_style_db_point)
        self.window.wg_style_Symbol.addWidget(self.__pb_style_intesect)
        self.window.wg_style_Lim_angle.addWidget(self.__pb_style_lim_angle)
        self.window.wg_style_Area_intersect.addWidget(self.__pb_style_area_intesect)

        self.window.wg_style_Area_limit.addWidget(self.__pb_style_area_lim)
        self.window.wg_style_Area_gap.addWidget(self.__pb_style_area_gap)

    def __initTableList(self):
        '''sel_count=axipy.gui.selection_service.count
        if sel_count>0 :
            self.window.cb_source_table.addItem('Выборка')
        table_sel=axipy.gui.selection_service.table()
        '''
        list_table= axipy.app.mainwindow.catalog.tables
        for table in list_table:
            name=table.name
            self.window.cb_source_table.addItem(name)
    def __init_AreaUnits(self):
        #list_area_units=  axipy.cs.AreaUnit.list_all()
        list_area_units=AreaUnits.values()
        for a_unit in list_area_units:
            self.window.cb_AreaUnits.addItem(a_unit.description)
            self.window.cb_AreaUnits_lim.addItem(a_unit.description)
    def __getSelectUnitToSqKm(self,value):
        name_area_unit=self.window.cb_AreaUnits.currentText()
        unit_select=self.__find_area_unit(name_area_unit)
        val_sq_km=unit_select.to_unit(axipy.Unit.sq_km)
        return val_sq_km*value
    def __getSelectUnitToSqKmFrom(self,value,name_area_unit):
        #name_area_unit=self.window.cb_AreaUnits.currentText()
        unit_select=self.__find_area_unit(name_area_unit)
        val_sq_km=unit_select.to_unit(axipy.Unit.sq_km)
        return val_sq_km*value
    def __find_area_unit(self,name_unit):
        #list_area_units= axipy.cs.AreaUnit.list_all()
        list_area_units = AreaUnits.values()
        for unit in list_area_units:
            if unit.description==name_unit:
                return unit
        return None


