# -*- coding: utf-8 -*-
"""
Copyright (c) 2016 Biuro Urządzania Lasu i Geodezji Leśnej

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
OTHER DEALINGS IN THE SOFTWARE.
"""
"""Moduł etykietowania"""

#Marcin Śliwa
from qgis.core import *
from qgis.gui import *
from Mapa_PU.model.konfiguracja import Projekt
from Mapa_PU.model.baza_danych import Baza
from Mapa_PU.widok.etykietuj_obiekty import EtykietujObiektyDialog
from Mapa_PU.model.obiekty_podstawowe_model import ObiektyPodstawoweModel
from PyQt5.QtCore import * 

from Mapa_PU.kontroler.mapa import Mapa

from Mapa_PU.kontroler import komunikaty
from cmath import rect


class Etykiety:
    """Obiekt kontroluj�cy etykietowania"""
    
    def __init__(self,Mapa,iface,nazwaWarstwy,atrybuty,promien=1,zmianaNarzedzia=None):
        """konstruktor
        :param Mapa: obiekt mapy
        :param iface:obiekt qgisa
        :param promien:dokladnosc 
        :param zmianaNarzedzia: metoda wywoływana przy zmianie narzedzia w qgis
        """
        self.mapa=Mapa
        self.iface=iface
        self.obiekt=None
        self.__promien=promien
        self.zmianaNarzedzia=zmianaNarzedzia
        self.nazwaWarstwy=nazwaWarstwy
        self.warstwa=None
        self.atrybuty=atrybuty
            
    def wybierz_obiekt(self, punkt, przycisk):
        """"Metoda obsĹ‚ugujaca wybĂłr obiektu
        :param punkt: punkt wyboru obiektu
        :param przycisk:metoda wyboru
        """
        try:
            self.ustaw_warstwe()
            if self.kontroluj_warstwy(self.nazwaWarstwy)==False:
                return 
            if self.kontroluj_atrybuty(self.warstwa, self.atrybuty)==False:
                return 
            
            
            rect = QgsRectangle(punkt.x() - self.__promien,
                                punkt.y() - self.__promien,
                                punkt.x() + self.__promien,
                                punkt.y() + self.__promien)
            
            wynik = QgsFeatureRequest()
            wynik.setFilterRect(rect)
            
           
            
            
            
            
            self.obiekt=None
            for obiekt in self.warstwa.getFeatures(wynik):
                self.obiekt=obiekt
                id=int(obiekt.id())
                self.warstwa.select(id)
                
            
          
            
            if self.obiekt==None:
                komunikaty.usun()
                komunikaty.pasek(u'Nie wybrano obiektu. Proszę spróbować jeszcze raz', 3)
                return
            
            #Odłaczenie metody
            self.odlacz_wybor()
            
            #Wywołanie metody wpisania wartości
            self.__wpisz_wartosc(id,self.__wartosci)
            
            
            
            #Wywołanie metody konczacej działanie zapisu do obiektu
            self.__metoda_koncowa()
            
        except Exception as e:
           komunikaty.blad_systemowy(e) 
           
    
      
     
    def ustaw_wartosci(self,wartosci):
        """Ustawia wartości
        :param wartosci:wartosci do wpisania w obiekt
        """
        self.__wartosci=wartosci
    
    def ustaw_warstwe(self):
        """Ustawia warstwę kóra bedzie aktualizowana"""
        if self.mapa.czyWarstwaJestWybrana(self.nazwaWarstwy)==True:
            self.warstwa=self.mapa.warstwaZaznaczona()
        else:
            self.warstwa=self.mapa.warstwa_mapa(self.nazwaWarstwy)[0]
            
        
            
    def podlacz_wybor(self):
        """Włącza pobieranie obiektu z mapy""" 
        try:
                
            self.mapa.podlaczMetode(self.wybierz_obiekt,self.zmianaNarzedzia)
           
        except Exception as e:
            komunikaty.blad_systemowy(e)
            
    
    def odlacz_wybor(self):
        """Wyłącza pobieranie obiektu z mapy"""
        try:
            self.mapa.odlaczMetode(self.wybierz_obiekt,self.zmianaNarzedzia)
          
        except Exception as e:
            komunikaty.blad_systemowy(e)
                   
    
    def ustaw_metode_koncowa(self,metoda):
        """Ustawia metode wykonywana na koncu edycji
        :param metoda:metoda końcowa
        """
        self.__metoda_koncowa=metoda
        
    
    def __wpisz_wartosc(self,id,wartosci):
        """Wpisuje wrto�ci do obiekt�w warstwy
        :param id: id obiektu
        :param wartosci: wartosci wpisywane
        """
        try:
          
            self.warstwa.dataProvider().changeAttributeValues({ id : wartosci })
            
            
        except Exception as e:
            komunikaty.blad_systemowy(e)
    
    def __aktualizuj_atrybuty(self,obiekt):
        """Aktualizuje pola w obiekcie warstwy
        :param obiekt: obiekt aktualizowany
        """
        try:
            for klucz,wartosc in self.__wartosci.items():
               
                obiekt.setAttribute(klucz,wartosc)
        except Exception as e:
            komunikaty.blad_systemowy(e)
    
    def kontroluj_atrybuty(self,warstwa,atrybuty):
        """Kontroluje atrybuty warstwy
        :param warstwa: obiekt warstwy
        :param atrybuty: atrybuty do kontroli
        :return wynik kontroli
        """
        try:
            
            for atrybut in atrybuty:
                if warstwa.jestAtrybut(atrybut)==False:
                    komunikaty.blad(u"Błędna struktura", u"Brak odpowiedniej struktury dla warstwy %s" % warstwa.name())
                    return False
            return True
        except Exception as e:
            komunikaty.blad_systemowy(e)
    
    def kontroluj_warstwy(self,nazwa):
        """Kontrola dostepności warstwy po nazwa
        :param nazwa: nazwa warstwy
        :return wynik kontroli
        """
        try:
           
               
            #Kontrola wyboru warstwy
            if self.mapa.czyWarstwaJestWybrana(nazwa)==True:
                #Jeżeli warstwa jest wybrana to musi byc zaznaczona
                if self.mapa.czyWarstwaJestZaznaczona(self.mapa.warstwaZaznaczona())==False:
                    komunikaty.blad(u'Warstwy', u"Wybrana warstwa '%s' nie jest dodana do mapy. Proszę dodać warstwę do mapy!" % (nazwa))
                    return False
                return True
            
            #Kontrola warstwy w widoku
            if self.mapa.czyWarstwaJestwWidoku(nazwa)==False:
                    komunikaty.blad(u'Brak warstwy', u'Proszę dodać warstwę '+nazwa+u' do mapy !')
                    return False    
            
            
            ilosc=len(self.mapa.warstwa_mapa(nazwa))
            if ilosc==1:
                return True
            else:
                komunikaty.blad(u'Warstwy', u"Na mapie jest więcej niż jedna warstwa '%s'. Proszę zaznaczyć warstwę którą chcesz etykietować !" % (nazwa))
                return False
           
            
            return True
        except Exception as e:
            komunikaty.blad_systemowy(e)
    
class EtykietyTabel(Etykiety):
    """Etykietuje obiekty na podstawie widoku TableView"""
    
    
    def __init__(self,iface,nazwaWarstwy,atrybuty,projekt,Mapa,promien=1):
        """konstruktor
        :param Mapa: obiekt mapy
        :param iface:obiekt qgisa
        :param promien:dokladnosc 
        :param projekt: obiekt konfiguracji
        """
        Etykiety.__init__(self,Mapa,iface,nazwaWarstwy,atrybuty,promien)
        self.iface=iface
       
        self.__projekt=projekt
      
        self.__mapa=Mapa
    
    def konfiguruj(self,zapytanie,naglowkiKolumn,mapowanie,tytul):
        """Konfiguracja obiektu etykietowania
        :param atrybuty: atrybuty
        :param zapytanie: zapytanie do bazy
        :param naglowkiKolumn: nagłówki kolumn wyswietlane
        :param mapowanie:zmapowanie wartosci i kolumny do zapisu w obiekcie z mapy - w tej chwili tylko podanie nazwy logiki
        :param tytul: tytuł wyswietlany 
        """
        try:
                        
            #zapytanie do pobrania danych z bazy    
            self.__zapytanie=zapytanie
            self.__naglowki= naglowkiKolumn
            self.__mapowanie=mapowanie
            self.__tytul=tytul
        except Exception as e:
            komunikaty.blad_systemowy(e)
        
             
    def etykietuj(self):
        """"Etykietowanie"""
        try:
            #Kontrola istnienia warstwy
            if self.kontroluj_warstwy(self.nazwaWarstwy)==False:
                return
            
            self.ustaw_warstwe()
            
            if self.kontroluj_atrybuty(self.warstwa, self.atrybuty)==False:
                return
                        
            komunikaty.czekanie("Wczytywanie danych")
                    
            self.ustaw_metode_koncowa(self.metoda_koncowa)
            self.__wczytaj_dane()
            self.__wczytaj_model()
            
            if self.__model.rowCount(self.iface)==0:
                komunikaty.usun()
                komunikaty.informacja(u"Brak danych", u"W bazie danych brak wartości do etykietowania.")
                return
               
            self.__wczytaj_widok()
            #Podpięcie metodya wyboru wiersza
            ret=self.__okno.ustawSelekcje(self.wybierz_wiersz,self.podlacz_wybor)
            
            #
            komunikaty.usun()
            
            
                
            
            self.__okno.show()
            
           
            
        except Exception as e:
            komunikaty.blad_systemowy(e)
       
            
    def wybierz_wiersz(self,zaznaczony,odznaczony):
            """Ustawia wybrany wiersz jako bieżący
            :param zaznaczony: obiekt zaznaczony
            :param odznaczony: obiekt odznaczony 
            """
            try:
                self.__bierzacyWiersz=self.__okno.zaznaczonyWiersz()
                if self.__bierzacyWiersz==None:
                    return
                
                if self.kontroluj_warstwy(self.nazwaWarstwy)==False:
                    return
                self.ustaw_warstwe()
                if self.kontroluj_atrybuty(self.warstwa, self.atrybuty)==False:
                    return
                
                
                
                wartosci={}
                for k,v in self.__mapowanie.items():
                    wartosci[self.warstwa.idxPola(k)]=zaznaczony.indexes()[v].data()
             
                
                               
                           
                self.ustaw_wartosci(wartosci)
                  
                self.podlacz_wybor()
            except Exception as e:
                komunikaty.blad_systemowy(e)   
    
    def metoda_koncowa(self):
        """Wywołanie metody na koniec działania aktualizacji obiektu"""
        try:
          
            self.__usun_wiersz()
            
        except Exception as e:
            komunikaty.blad_systemowy(e)
                
    def __usun_wiersz(self):
        """Usówa wiersz z modelu"""
        try:
          
            self.__model.removeRows(self.__bierzacyWiersz.row())
                        
            #Ustawienie aktywnego wiersza na zgodny z zaznaczeniem widoku             
            self.__bierzacyWiersz=self.__okno.zaznaczonyWiersz()
            
           
            
        except Exception as e:
            komunikaty.blad_systemowy(e)
            
    def __wczytaj_dane(self):
        """"Wczytanie danych z bazy"""
        try:
         
            
            self.__baza=Baza(self.__projekt.plikBazaTaksator)
            self.__baza.polaczOdbc()
            self.__dane=self.__baza.wykonajZapytanie(self.__zapytanie)
            self.__baza.zamknijPolaczenie()
            
        except Exception as e:
            komunikaty.blad_systemowy(e)
            
    def __wczytaj_model(self):
        """Wczytuje dane do modelu"""
        try:
            self.__model=ObiektyPodstawoweModel(self.__dane,self.__naglowki,self.iface)
        except Exception as e:
            komunikaty.blad_systemowy(e)
            
    def __wczytaj_widok(self):
        """Wczytuje widok"""
        try:
            self.__okno=EtykietujObiektyDialog(self.__tytul,self.iface.mainWindow())
            self.__okno.ustawModel(self.__model)
            self.__okno.ustawWysokoscWiersza(len(self.__dane), 18)
            self.__okno.zamknij=self.odlacz_wybor
        except Exception as e:
            komunikaty.blad_systemowy(e)
   

    
   
        