# -*- coding: utf-8 -*-
from Mapa_PU.swdl.kontroler.database_helper import DatabaseHelper
from Mapa_PU.model.baza_danych import Baza
from PyQt5.QtWidgets import QProgressBar
from qgis.gui import QgsMessageBarItem
from Mapa_PU.widok.pasek_wiadomosci import PasekWiadomosc
from Mapa_PU.model.wynik_kontroli import WynikKontroli, Result, TypeOfControl
from Mapa_PU.model.raport import Report
from Mapa_PU.kontroler import komunikaty
from Mapa_PU.kontroler.kontrola_opisu_taksacyjnego import KontroleOpisuTaksacyjnego

import os
#from pip._vendor.distlib import database

class DatabaseControler():
    """Kontoluje dane i warstwy pod kątem eksportu do pliku swdl"""
    
    
    
    def __init__(self,database_helper:DatabaseHelper,wersja):
        self.database_helper=database_helper
        self.__wersja=wersja
    
    def control(self,root,swdl_version,pasek:PasekWiadomosc,kontrola_geometrii,kontrola_danych,kontrola_opisu:KontroleOpisuTaksacyjnego,database:Baza,path)->str:
        """Kontroluje bazę danych i warstwy"""
        try:
            self.__path=path
            self.ret=[]
            self.__checks=[]
            self.geometry=kontrola_geometrii
            self.dane=kontrola_danych
                        
            #kontrola opisu taksacyjnego
            self.control_description(pasek,kontrola_opisu)
            #kontrola danych bazy
            self.control_data(root,swdl_version,database,pasek) 
            #kontrola geometrii
            self.control_geometry(pasek)
            
            report=self.create_report(self.__checks)
            
            return report
        except Exception as e:
            raise e
    
    def control_description(self,pasek:PasekWiadomosc,kontrola_opisu:KontroleOpisuTaksacyjnego):
        """kontrola opisu taksacyjnego
        """
        try:
            heading='Kontrole poprzedzające wygenerowanie SWDL\nWersja programu Mapa PU {}\nAby wygenerować SWDL należy poprawić poniższe błędy.\n'.format(self.__wersja)
            errors=kontrola_opisu.kontroluj(pasek,swdl=True)
            for error in errors:
                if error.is_error==True:
                    result=WynikKontroli(error.nazwa,None,None,None)
                    result.add_result(Result(error.nazwa,'',error.errors,TypeOfControl.DESCRIPTION))
                    self.add_control(result)
            
        except Exception as e:
            raise e
    
    def control_data(self,root,swdl_version,baza:Baza,pasek:PasekWiadomosc):
        """Kontrola danych"""
        try:
            #kontrola bazy
            ret=self.dane.kontrola_f_parameter(baza, pasek)
            self.add_control(ret)
              
            ret=self.dane.kontrola_f_measure(baza, pasek)
            self.add_control(ret)
 
            ret=self.dane.kontrola_f_parcel(baza,pasek)
            self.add_control(ret)
  
            ret=self.dane.kontrola_pow(baza,pasek)
            self.add_control(ret)
            
            #kontrola słowników
            #Kontrola CAUSE_CD
            ret=self.dane.kontrolujSlownik(root,swdl_version ,baza, 'F_END_CAUSE_DIC','CAUSE_CD', 'causeCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_AREA_TYPE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_AREA_TYPE_DIC','AREA_TYPE_CD', 'areaTypeCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_MOISTENING_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_MOISTENING_DIC','MOISTURY_CD', 'moistureCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_LOCATION_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_LOCATION_DIC','LOCATION_CD', 'locationCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_MIXTURE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_MIXTURE_DIC','MIXTURE_CD', 'mixtureCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_PART_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_PART_DIC','PART_CD', 'partCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_PLANT_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_PLANT_DIC','PLANT_CD', 'plantCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_PHENOMENA_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_PHENOMENA_DIC','PHENOMENA_CD', 'phenomenaCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SITE_TYPE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SITE_TYPE_DIC','SITE_TYPE_CD', 'siteTypeCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_POSITION_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_POSITION_DIC','POSITION_CD', 'positionCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_RELIEF_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_POSITION_DIC','RELIEF_CD', 'reliefCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_DEGRADATION_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_DEGRADATION_DIC','DEGRADATION_CD', 'degradationCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_VEG_COVER_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_VEG_COVER_DIC','VEG_COVER_CD', 'vegCoverCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SILVICULTURE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SILVICULTURE_DIC','SILVICULTURE_CD', 'silvicultureCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_FOREST_FUNC_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_FOREST_FUNC_DIC','FOREST_FUNC_CD', 'forestFuncCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_STAND_STRUCT_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_STAND_STRUCT_DIC','STAND_STRUCT_CD', 'standStructCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SLOPE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SLOPE_DIC','SLOPE_CD', 'slopeCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_EXPOSURE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_EXPOSURE_DIC','EXPOSURE_CD', 'exposureCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SOIL_PEC_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SOIL_PEC_DIC','SOIL_PEC_CD', 'soilPecCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SOIL_SUBTYPE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SOIL_SUBTYPE_DIC','SOIL_SUBTYPE_CD', 'soilSubTypeCd', pasek,None ,None)
            self.add_control(ret)
            #Kontrola F_RECONSTRUCTION_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_RECONSTRUCTION_DIC','RECONSTR_CD', 'reconstrCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_GROWTH_PHASE_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_GROWTH_PHASE_DIC','PHASE_CD', 'phaseCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_FOREST_PEC_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_GROWTH_PHASE_DIC','F_FOREST_PEC_DIC', 'forestPecDic', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_PROT_CATEG_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_PROT_CATEG_DIC','PROT_CATEGORY_CD', 'categoryCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_TREE_SPECIES
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_TREE_SPECIES','SPECIES_CD', 'speciesCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_DENSITY_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_DENSITY_DIC','DENSITY_CD', 'densityCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_TREE_STOCK_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_TREE_STOCK_DIC','TREE_STOCK_CD', 'treeStockCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_SITE_CLASS_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SITE_CLASS_DIC','SITE_CLASS_CD', 'siteClassCd', pasek,None ,True)
            self.add_control(ret)
            #Kontrola F_ENV_PROTECT_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_ENV_PROTECT_DIC','PROTECT_AREA_CD', 'naturalValueCd', pasek,None ,False)
            self.add_control(ret)
            #Kontrola F_PROT_AREA_DIC 
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_PROT_AREA_DIC','PROTECT_AREA_CD', 'protectAreaCD', pasek,None ,False)
            self.add_control(ret)
            #Kontrola F_SOIL_SPECIES_DIC
            ret=self.dane.kontrolujSlownik(root, swdl_version,baza, 'F_SOIL_SPECIES_DIC','SOIL_SPECIES_CD', 'soilSpeciesCd', pasek,None ,False)
            self.add_control(ret)
           
            
        except Exception as e:
            raise e
    
    def add_control(self,control):
        """Dodaje kontrolę do listy"""
        self.__checks.append(control)
    
    def control_geometry(self,pasek:PasekWiadomosc):
        """Kontrola geometrii"""
        try:
            #Kontrola duplikatów
            ret=self.control_layer_duplicates(pasek,'OP_POW', 'ADR_BDL')
            self.add_control(ret)
            ret=self.control_layer_duplicates(pasek,'OP_ODDZ', 'ADR_BDL')
            self.add_control(ret)
#             pasek.setText("Kontrola warstwy O_PODST")
#             pasek.setProgressValue(6)
#             self.control_layer(u'O_PODST')
#             #self.control_slot('O_PODST')
#                  
#             pasek.setText("Kontrola warstwy POW")
#             pasek.setProgressValue(12)
#             self.control_layer(u'POW')
#             #self.control_slot('POW')
#          
#             pasek.setText("Kontrola warstwy ODDZIAL")
#             pasek.setProgressValue(18)
#             self.control_layer(u'ODDZIAL')
#             #self.control_slot('ODDZIAL')
#         
#             pasek.setText("Kontrola warstwy PNSW")
#             pasek.setProgressValue(24)
#             self.control_layer(u'PNSW')
#             #self.control_slot('PNSW')
#          
#             pasek.setText("Kontrola warstwy DZ_EWID")
#             pasek.setProgressValue(30)
#             self.control_layer(u'DZ_EWID')
#             #self.control_slot('DZ_EWID')
#          
#             pasek.setText("Kontrola warstwy UZYTKI")
#             pasek.setProgressValue(36)
#             self.control_layer(u'UZYTKI')
#             #self.control_slot('UZYTKI')
        
        
#         # POW -> ODDZIAL:
#             pasek.setText("Kontrola zawierania POW -> ODDZIAL")
#             pasek.setProgressValue(42)
#             self.control_concluding(nazwa_warstwy_1 = 'ODDZIAL', nazwa_warstwy_2 = 'POW', pola_klucza = ['ADR_BDL'], dlugosc_klucza=17)
#         
#         
#         # UZYTKI - > DZ_EWID:
#             pasek.setText("Kontrola zawierania UZYTKI - > DZ_EWID")
#             pasek.setProgressValue(48)
#             self.control_concluding(nazwa_warstwy_1 = 'DZ_EWID', nazwa_warstwy_2 = 'UZYTKI', pola_klucza = ['ADR_ADM','NR_EW'])
#         
#          
#         # PNSW -> POW:
#             pasek.setText("Kontrola zawierania PNSW -> POW")
#             pasek.setProgressValue(54)
#             self.control_concluding(nazwa_warstwy_1 = 'POW', nazwa_warstwy_2 = 'PNSW', pola_klucza = ['ADR_BDL'])
#         
#         
#         # PNSW -> DZ_EWID:
#             pasek.setText("Kontrola zawierania PNSW -> DZ_EWID")
#             pasek.setProgressValue(60)
#             self.control_concluding(nazwa_warstwy_1 = 'DZ_EWID', nazwa_warstwy_2 = 'PNSW', pola_klucza = ['NR_EW','ADR_ADM'])
#         
#         
#         # OS_PKT -> POW:
#             pasek.setText("Kontrola warstwy OS_PKT -> POW")
#             pasek.setProgressValue(66)
#             self.control_concluding(nazwa_warstwy_1 = 'POW', nazwa_warstwy_2 = 'OS_PKT', pola_klucza = ['ADR_BDL'])
#         
#         
#         # OS_POW -> POW:
#             pasek.setText("Kontrola warstwy OS_POW -> POW")
#             pasek.setProgressValue(72)
#             self.control_concluding(nazwa_warstwy_1 = 'POW', nazwa_warstwy_2 = 'OS_POW', pola_klucza = ['ADR_BDL'])
#             
#         
#         # O_PODST -> DZ_EWID:
#             pasek.setText("Kontrola zawierania O_PODST -> DZ_EWID")
#             pasek.setProgressValue(78)
#             self.control_concluding(nazwa_warstwy_1 = 'DZ_EWID', nazwa_warstwy_2 = 'O_PODST', pola_klucza = ['ADR_ADM','NR_EW'])
#        
#         
#         # O_PODST -> UZYTKI:
#             pasek.setText("Kontrola zawierania O_PODST -> UZYTKI")
#             pasek.setProgressValue(84)
#             self.control_concluding(nazwa_warstwy_1 = 'UZYTKI', nazwa_warstwy_2 = 'O_PODST', pola_klucza = ['ADR_ADM','NR_EW','NR_KONT'])
#         
#         #Do wyłączenia po testach
#         # UZYTKI -> O_PODST:
# #             pasek.setText("Kontrola zawierania UZYTKI -> O_PODST")
# #             pasek.setProgressValue(90)
# #             self.control_concluding(nazwa_warstwy_1 = 'O_PODST', nazwa_warstwy_2 = 'UZYTKI', pola_klucza = ['ADR_ADM','NR_EW','NR_KONT'])
#         
#         # OP_POW - > POW:
#             pasek.setText("Kontrola zawierania OP_POW - > POW")
#             pasek.setProgressValue(92)
#             self.control_concluding(nazwa_warstwy_1 = 'POW', nazwa_warstwy_2 = 'OP_POW', pola_klucza = ['ADR_BDL'])
#         
#         
#         # OP_ODDZ - > POW:
#             pasek.setText("Kontrola zawierania OP_ODDZ - > POW")
#             pasek.setProgressValue(98)
#             self.control_concluding(nazwa_warstwy_1 = 'ODDZIAL', nazwa_warstwy_2 = 'OP_ODDZ', pola_klucza = ['ADR_BDL'],  dlugosc_klucza=17)
        
            
        except Exception as e:
            raise e
       
    def control_layer_duplicates(self,pasek:PasekWiadomosc,name:str,field='ADR_BDL'):
        """"Kontroluje duplikaty warstwy"""
        try:
            errors=set([er[0] for er in self.geometry.kontolaDuplikatow(pasek,name,field)])
            
            
            
            nazwa=u'Kontrola zdublowanych rekordów'
            
            wynik=WynikKontroli(nazwa,'','- warstwa {} zawiera zdublowany rekord'.format(name),name)
            #nie jest to optymalny sposów #wykorzystać 
            
            if len(errors)>0:
                wynik.add_result(Result(nazwa,'warstwa {} zawiera zdublowany rekord'.format(name),errors,TypeOfControl.DATA))
            wynik.bledyWarstwy=errors
            wynik.bledyBazy=[]
            return wynik
        except Exception as e:
            raise e
       
    def create_report(self,errors:[])->Report:
        """Tworzy raport z błędów"""
        try:
            heading='Kontrole poprzedzające wygenerowanie SWDL\n Wersja programu Mapa PU {}\n Aby wygenerować SWDL należy poprawić poniższe błędy'.format(self.__wersja)
            report=Report(self.__path,'Kontrola_exportu_SWDL_',heading)
            for error in errors:
                if len(error.results)>0:
                    report.is_error=True
                    report.control_header(error.nazwa)
                    report.body(error.results)
                    report.add_result(error.results)
                    report.end_body()
            return report
            
        except Exception as e:
            raise e 
        
