# -*- coding: utf-8 -*-
"""
/***************************************************************************
 HuntRegister
                                 A QGIS plugin
 This plugin can be used to create hunt registers
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2020-03-26
        git sha              : $Format:%H$
        copyright            : (C) 2020 by Simon Hodrus
        email                : s.hodrus@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from qgis.PyQt.QtCore import Qt, QEvent, QSettings, QPoint, QDate
from qgis.PyQt.QtWidgets import QApplication, QDialog, QDialogButtonBox, QMessageBox, QFileDialog
from qgis.PyQt.QtPrintSupport import QPrintDialog, QPrinter
from qgis.PyQt.QtSql import QSqlQuery

from qgis.PyQt import QtCore
from qgis.PyQt import QtWidgets
from qgis.PyQt.QtGui import QFont

#from qgis.PyQt import uic

from qgis.core import QgsProject, QgsMessageLog, Qgis
from qgis.gui import QgsMapTool, QgsAuthConfigSelect, QgsRubberBand

import os
import re
import numpy as np
import math as mt
from collections import Counter


try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s


#######################################################
# HAdd (add parcels to the hunt layer map tool)
#######################################################
class HAdd(QgsMapTool):
    """select deselect parcels to hunt selection layer"""

    def __init__(self, plugin):
        """Constructor.

        :param plugin: The HuntRegsiter main plugin
            which provides access to alkis and core functionality
        :type plugin: HuntRegister
        """
        QgsMapTool.__init__(self, plugin.iface.mapCanvas())
        self.plugin = plugin
        self.iface = plugin.iface                                                                                                                               # qgis QgsInterface

    def canvasPressEvent(self, event):
        """canvas pressed event"""
        if self.plugin.core.getHLayer() is None:                                                                                                                # in case the target layer does not exist show user message and try to fiy the layer
            self.iface.messageBar().pushMessage(
                "Fehler", "'Jagd-Flächenmarkierung' fehlt in 'Markierungen' Gruppe. Reparaturversuch gestartet", level=Qgis.Critical, duration=10)
            self.plugin.initLayers()

    def canvasMoveEvent(self, event):
        """canvas mouse move event"""
        return

    def canvasReleaseEvent(self, event):
        """canvas mouse release event"""
        self.plugin.core.hitOnHighlight(event)


class UtilSummary(object):
    """Utilization summary object"""                                                                                                                            # used to summarize for the same utilization of multiple parcels
    def __init__(self, queryData):
        """init with the data of the first parcel"""
        self.uNr = queryData['nutzsl']                                                                                                                          # utilization number
        self.uName = queryData['nutzung']                                                                                                                       # utilization name
        self.surTot = float(queryData['fl'])                                                                                                                    # area of this utilization
        self.surTotHa = self.SurToHa()                                                                                                                          # area of this utilization in ha
        self.parcelCount = 1

    def Update(self, queryData):
        """update this utilization object by adding another parcel information"""
        self.surTot += float(queryData['fl'])
        self.surTotHa = self.SurToHa()
        self.parcelCount += 1

    def SurToHa(self):
        """get the total surface area in ha"""
        return round(self.surTot / 10000, 2)


#######################################################
# SelectUtilisationUI (used to select parcels based on utilization and number)
#######################################################
class SelectUtilisationUI(QDialog):
    """SelectUtilisationUI (used to select parcels based on utilization and number)"""
    def __init__(self, data):
        QDialog.__init__(self)
        """Constructor.

        :param data: the data used to generate the selction lists
        :type data: dict
        """
        self.setupUi(self)
        self.selUtilisationText = []                                                                                                                            # selected text field of the utilization shown to the user
        self.selUtilisationData = []                                                                                                                            # seleted complete data object of the utilization, the datatype is a dictionary
        self.listUtilBitmap = []                                                                                                                                # bitmap for checked or unchecked utilizations
        self.selGemarkungText = []                                                                                                                              # selected text field of the (Gemarkung) shown to the user
        self.selGemarkungData = []                                                                                                                              # selected data object of the (Gemarkung) this is just the number as string
        self.listGemaBitmap = []                                                                                                                                # bitmap for checked or unchecked (Gemarkung)
        self.loadLists(self.listUtilisation, data["nutzung"], "nutzung")                                                                                        # init the utilization list view
        self.loadLists(self.listGemarkung, data["gemarkung"], "gemashl")                                                                                        # init the (Gemarkung) list view

    def setupUi(self, SelectUtilisation):
        SelectUtilisation.setObjectName(_fromUtf8("SelectUtilisation"))
        SelectUtilisation.setWindowModality(QtCore.Qt.WindowModal)

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHeightForWidth(SelectUtilisation.sizePolicy().hasHeightForWidth())

        SelectUtilisation.resize(670, 650)
        SelectUtilisation.setWindowTitle(_fromUtf8("Ergänzende Selektierung nach Nutzung & Gemarkung"))
        SelectUtilisation.setSizePolicy(sizePolicy)
        SelectUtilisation.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        SelectUtilisation.setModal(True)

        self.DialogBB = QDialogButtonBox(SelectUtilisation)
        self.DialogBB.setGeometry(QtCore.QRect(15, 5, 650, 30))
        self.DialogBB.setSizePolicy(sizePolicy)
        self.DialogBB.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        self.DialogBB.setOrientation(QtCore.Qt.Horizontal)
        self.DialogBB.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
        self.DialogBB.setObjectName(_fromUtf8("DialogBB"))

        self.listUtilisation = QtWidgets.QListWidget(SelectUtilisation)
        self.listUtilisation.setGeometry(QtCore.QRect(10, 60, 655, 435))
        self.listUtilisation.setSizePolicy(sizePolicy)
        self.listUtilisation.setAutoScroll(False)
        self.listUtilisation.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listUtilisation.setAlternatingRowColors(True)
        self.listUtilisation.setSpacing(1)
        self.listUtilisation.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.listUtilisation.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
        self.listUtilisation.setViewMode(QtWidgets.QListView.ListMode)
        self.listUtilisation.setSelectionRectVisible(True)
        self.listUtilisation.setObjectName(_fromUtf8("listUtilisation"))
        self.listUtilisation.setSortingEnabled(True)

        self.listGemarkung = QtWidgets.QListWidget(SelectUtilisation)
        self.listGemarkung.setGeometry(QtCore.QRect(10, 565, 655, 80))
        self.listGemarkung.setSizePolicy(sizePolicy)
        self.listGemarkung.setAutoScroll(False)
        self.listGemarkung.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listGemarkung.setAlternatingRowColors(True)
        self.listGemarkung.setSpacing(1)
        self.listGemarkung.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.listGemarkung.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
        self.listGemarkung.setViewMode(QtWidgets.QListView.ListMode)
        self.listGemarkung.setSelectionRectVisible(True)
        self.listGemarkung.setObjectName(_fromUtf8("listGemarkung"))
        self.listGemarkung.setSortingEnabled(True)

        font = QFont()
        font.setPointSize(10)

        self.lblUtilisation = QtWidgets.QLabel(SelectUtilisation)
        self.lblUtilisation.setGeometry(QtCore.QRect(10, 40, 90, 16))
        self.lblUtilisation.setSizePolicy(sizePolicy)
        self.lblUtilisation.setFont(font)
        self.lblUtilisation.setObjectName(_fromUtf8("lblUtilisation"))
        self.lblUtilisation.setText(_fromUtf8("Nutzungen"))

        self.lblUtilCount = QtWidgets.QLabel(SelectUtilisation)
        self.lblUtilCount.setGeometry(QtCore.QRect(595, 40, 80, 16))
        self.lblUtilCount.setSizePolicy(sizePolicy)
        self.lblUtilCount.setFont(font)
        self.lblUtilCount.setObjectName(_fromUtf8("lblUtilCount"))

        self.lblGemarkung = QtWidgets.QLabel(SelectUtilisation)
        self.lblGemarkung.setGeometry(QtCore.QRect(10, 545, 90, 16))
        self.lblGemarkung.setSizePolicy(sizePolicy)
        self.lblGemarkung.setFont(font)
        self.lblGemarkung.setObjectName(_fromUtf8("lblGemarkung"))
        self.lblGemarkung.setText(_fromUtf8("Gemarkung"))

        self.lblGemaCount = QtWidgets.QLabel(SelectUtilisation)
        self.lblGemaCount.setGeometry(QtCore.QRect(595, 545, 80, 16))
        self.lblGemaCount.setSizePolicy(sizePolicy)
        self.lblGemaCount.setFont(font)
        self.lblGemaCount.setObjectName(_fromUtf8("lblGemaCount"))

        self.btnCheck = QtWidgets.QPushButton(SelectUtilisation)
        self.btnCheck.setGeometry(QtCore.QRect(508, 510, 75, 23))
        self.btnCheck.setSizePolicy(sizePolicy)
        #self.btnCheck.setFont(QFont("", pointSize=8))
        self.btnCheck.setText(_fromUtf8("Anwählen"))
        self.btnCheck.setObjectName(_fromUtf8("btnCheck"))
        self.btnCheck.setEnabled(False)

        self.btnClear = QtWidgets.QPushButton(SelectUtilisation)
        self.btnClear.setGeometry(QtCore.QRect(590, 510, 75, 23))
        self.btnClear.setSizePolicy(sizePolicy)
        #self.btnClear.setFont(QFont("", pointSize=8))
        self.btnClear.setText(_fromUtf8("Alle abwählen"))
        self.btnClear.setObjectName(_fromUtf8("btnClear"))

        self.DialogBB.accepted.connect(SelectUtilisation.accept)
        self.DialogBB.rejected.connect(SelectUtilisation.reject)
        self.listUtilisation.itemChanged.connect(self.itemChangedUtil)
        self.listGemarkung.itemChanged.connect(self.itemChangedGema)
        self.listUtilisation.itemSelectionChanged.connect(self.itmSelChanged)
        self.listGemarkung.itemSelectionChanged.connect(self.itmSelChanged)
        self.btnCheck.clicked.connect(self.checkSelected)
        self.btnClear.clicked.connect(self.clearChecks)

        QtCore.QMetaObject.connectSlotsByName(SelectUtilisation)

    def itemChangedUtil(self, itm):
        """A utilization list item changed => get checked state and update bitmap and counter"""
        self.itmSelChanged()                                                                                                                                    # update ui (enable disable buttons)
        self.listUtilBitmap[itm.data(4)] = bool(itm.checkState())                                                                                               # update the boolean bitmap with the current checked state
        self.lblUtilCount.setText(_fromUtf8("%4d of %4d" % (sum(self.listUtilBitmap), len(self.listUtilBitmap))))                                               # reset the text of the checked counter

    def itemChangedGema(self, itm):
        """A gemarkung list item changed => get checked state and update bitmap and counter"""
        self.itmSelChanged()                                                                                                                                    # update ui (enable disable buttons)
        self.listGemaBitmap[itm.data(4)] = bool(itm.checkState())                                                                                               # update the boolean bitmap with the current checked state
        self.lblGemaCount.setText(_fromUtf8("%4d of %4d" % (sum(self.listGemaBitmap), len(self.listGemaBitmap))))                                               # reset the text of the checked counter

    def clearChecks(self):
        """clear all checked items for both lists and also clear user selections"""
        lUtil = [self.listUtilisation.item(it) for it in range(self.listUtilisation.count()) if self.listUtilisation.item(it).checkState()]                     # checked items of utilization list
        lGema = [self.listGemarkung.item(it) for it in range(self.listGemarkung.count()) if self.listGemarkung.item(it).checkState()]                           # checked items of gemarkung list

        for itm in lUtil:                                                                                                                                       # uncheck checked utilization items
            itm.setCheckState(QtCore.Qt.Unchecked)
        for itm in lGema:                                                                                                                                       # uncheck checked gemarkung items
            itm.setCheckState(QtCore.Qt.Unchecked)
        for itm in self.listUtilisation.selectedItems():                                                                                                        # deselect selected utilization items
            itm.setSelected(False)
        for itm in self.listGemarkung.selectedItems():                                                                                                          # deselect selected gemarkung items
            itm.setSelected(False)

    def checkSelected(self):
        """check all selected items in gemarkung and utilization lists"""
        selUtilItms = self.listUtilisation.selectedItems()
        selGemaItms = self.listGemarkung.selectedItems()
        for itm in selUtilItms:
            itm.setCheckState(QtCore.Qt.Checked)
        for itm in selGemaItms:
            itm.setCheckState(QtCore.Qt.Checked)
        self.btnCheck.setEnabled(False)

    def itmSelChanged(self):
        """enable 'check'-button in case there is a selected item in one of the lists which is not yet checked """
        selUtilItms = self.listUtilisation.selectedItems()
        selGemaItms = self.listGemarkung.selectedItems()
        lUtil = [itm for itm in selUtilItms if not itm.checkState()]                                                                                            # list of selected and unchecked items in utilization list
        lGema = [itm for itm in selGemaItms if not itm.checkState()]                                                                                            # list of selected and unchecked items in gemarkung list
        self.btnCheck.setEnabled((len(lUtil) + len(lGema) > 0))

    def loadLists(self, listObj, dictList, textAtt):
        """initialize listviews by populating with content
        listObj: is the target list
        dictList: is the data dictionary
        textAtt: is the dictionary key for teh text attribute"""

        listObj.clear()                                                                                                                                         # clear the list in case of repopulation

        for c, data in enumerate(dictList):                                                                                                                     # enumerate the data and create listview items
            item = QtWidgets.QListWidgetItem()
            item.setData(3, data)                                                                                                                               # datafield number three is the first empty field of an listview item and is used to store the object data
            item.setData(4, c)                                                                                                                                  # set the initial order key used in bitmap list
            item.setText(_fromUtf8(data[textAtt]))
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            listObj.addItem(item)

            if(listObj == self.listUtilisation):                                                                                                                # in case this object already has information about the items to be checked => check the bitmap entry and in the next step the item
                checked = (data[textAtt] in self.selUtilisationText)
                self.listUtilBitmap.append(checked)
            elif(listObj == self.listGemarkung):                                                                                                                # in case this object already has information about the items to be checked => check the bitmap entry and in the next step the item
                checked = (data[textAtt] in self.selGemarkungText)
                self.listGemaBitmap.append(checked)
            else:
                return

            if(checked):                                                                                                                                        # check the item
                item.setCheckState(QtCore.Qt.Checked)
            else:
                item.setCheckState(QtCore.Qt.Unchecked)

    def reject(self):
        """dialog rejection result"""
        self.Rejected = 1
        self.Accepted = 0
        self.done(0)

    def accept(self):
        """dialog accepted result"""                                                                                                                            # evaluate the selected items of all listviews and create selection lists containing the user selected data
        self.clearSelLists()                                                                                                                                    # clear the selection lists in case this object is reused
        for it in range(self.listGemarkung.count()):                                                                                                            # fill selection lists for gemarkung
            itm = self.listGemarkung.item(it)
            if(itm.checkState()):
                self.selGemarkungText.append(itm.text())
                self.selGemarkungData.append(itm.data(3))

        if (len(self.selGemarkungText) == 0):
            QMessageBox.information(None, "Fehler", "Keine Gemarkung ausgewählt")
            return

        for it in range(self.listUtilisation.count()):                                                                                                          # fill selection lists for utilization
            itm = self.listUtilisation.item(it)
            if(itm.checkState()):
                self.selUtilisationText.append(itm.text())
                self.selUtilisationData.append(itm.data(3))

        if (len(self.selUtilisationText) == 0):
            QMessageBox.information(None, "Fehler", "Keine Nutzung ausgewählt")
            return

        self.Rejected = 0
        self.Accepted = 1
        self.done(1)

    def clearSelLists(self):
        """clear all selection lists"""
        self.selUtilisationText = []
        self.selUtilisationData = []
        self.selGemarkungText = []
        self.selGemarkungData = []


#######################################################
# CalculatePayoffUI (shows hunt register form before calculation)
#######################################################
class CalculatePayoffUI(QDialog):
    """shows hunt register form before calculation can be processed"""
    def __init__(self, utils):
        """Constructor.

        :param utils: list of all present utilizations
        :type data: list of dictionaries
        """
        QDialog.__init__(self)
        self.setupUi(self)
        self.varInit()                                                                                                                                          # init all relevant variables
        self.loadList(utils, "nutzung", "nutzshl", [])                                                                                                          # init the listview from the utils list and pass the dictioary keys, and the last selection list, used to reload a previous state

    @property
    def entryData(self):                                                                                                                                        # return the form data for all entries
        entd = {}
        entd['docTitle'] = self.docTitle
        entd['payThresh'] = self.payoffThreshold
        entd['unitPrice'] = self.unitPrice
        return entd

    def setupUi(self, CalculatePayoff):
        CalculatePayoff.setObjectName(_fromUtf8("CalculatePayoff"))
        CalculatePayoff.setWindowModality(QtCore.Qt.WindowModal)
        CalculatePayoff.resize(400, 450)

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHeightForWidth(CalculatePayoff.sizePolicy().hasHeightForWidth())

        CalculatePayoff.setSizePolicy(sizePolicy)
        CalculatePayoff.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        CalculatePayoff.setModal(True)
        CalculatePayoff.setWindowTitle(_fromUtf8("Berechnungsgrundlage Jagdkataster"))

        self.DialogBB = QDialogButtonBox(CalculatePayoff)
        self.DialogBB.setGeometry(QtCore.QRect(10, 410, 380, 30))
        self.DialogBB.setSizePolicy(sizePolicy)
        self.DialogBB.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        self.DialogBB.setOrientation(QtCore.Qt.Horizontal)
        self.DialogBB.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
        self.DialogBB.setObjectName(_fromUtf8("DialogBB"))

        self.listExUtil = QtWidgets.QListWidget(CalculatePayoff)
        self.listExUtil.setGeometry(QtCore.QRect(10, 150, 380, 250))
        self.listExUtil.setSizePolicy(sizePolicy)
        self.listExUtil.setAutoScroll(False)
        self.listExUtil.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listExUtil.setAlternatingRowColors(True)
        self.listExUtil.setSpacing(1)
        self.listExUtil.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
        self.listExUtil.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectItems)
        self.listExUtil.setViewMode(QtWidgets.QListView.ListMode)
        self.listExUtil.setSelectionRectVisible(True)
        self.listExUtil.setObjectName(_fromUtf8("listExUtil"))
        self.listExUtil.setSortingEnabled(True)

        font = QFont()
        font.setPointSize(10)

        self.lblTextTitle = QtWidgets.QLabel(CalculatePayoff)
        self.lblTextTitle.setGeometry(QtCore.QRect(10, 10, 100, 15))
        self.lblTextTitle.setSizePolicy(sizePolicy)
        self.lblTextTitle.setFont(font)
        self.lblTextTitle.setObjectName(_fromUtf8("lblTextTitle"))
        self.lblTextTitle.setText(_fromUtf8("Dokumenttitel"))

        self.lblEuro = QtWidgets.QLabel(CalculatePayoff)
        self.lblEuro.setGeometry(QtCore.QRect(375, 85, 20, 15))
        self.lblEuro.setSizePolicy(sizePolicy)
        self.lblEuro.setFont(font)
        self.lblEuro.setObjectName(_fromUtf8("lblEuro"))
        self.lblEuro.setText(_fromUtf8(u"\u20AC"))

        self.lblThreshold = QtWidgets.QLabel(CalculatePayoff)
        self.lblThreshold.setGeometry(QtCore.QRect(220, 60, 150, 15))
        self.lblThreshold.setSizePolicy(sizePolicy)
        self.lblThreshold.setFont(font)
        self.lblThreshold.setObjectName(_fromUtf8("lblThreshold"))
        self.lblThreshold.setText(_fromUtf8("Auszahlungschwelle"))

        self.lblUnitPrice = QtWidgets.QLabel(CalculatePayoff)
        self.lblUnitPrice.setGeometry(QtCore.QRect(10, 60, 150, 15))
        self.lblUnitPrice.setSizePolicy(sizePolicy)
        self.lblUnitPrice.setFont(font)
        self.lblUnitPrice.setObjectName(_fromUtf8("lblUnitPrice"))
        self.lblUnitPrice.setText(_fromUtf8("Quadratmeterpreis"))

        self.lblUnitEu = QtWidgets.QLabel(CalculatePayoff)
        self.lblUnitEu.setGeometry(QtCore.QRect(165, 85, 30, 15))
        self.lblUnitEu.setSizePolicy(sizePolicy)
        self.lblUnitEu.setFont(font)
        self.lblUnitEu.setObjectName(_fromUtf8("lblUnitEu"))
        self.lblUnitEu.setText(_fromUtf8(u"\u20AC" + u"/" + u"m\xb2"))

        self.lblLBHeader = QtWidgets.QLabel(CalculatePayoff)
        self.lblLBHeader.setGeometry(QtCore.QRect(10, 130, 300, 18))
        self.lblLBHeader.setSizePolicy(sizePolicy)
        self.lblLBHeader.setFont(font)
        self.lblLBHeader.setObjectName(_fromUtf8("lblLBHeader"))
        self.lblLBHeader.setText(_fromUtf8("zu ignorierende Flurstücksnutzungen anwählen"))

        self.lblExUtilCount = QtWidgets.QLabel(CalculatePayoff)
        self.lblExUtilCount.setGeometry(QtCore.QRect(325, 130, 100, 15))
        self.lblExUtilCount.setSizePolicy(sizePolicy)
        self.lblExUtilCount.setFont(font)
        self.lblExUtilCount.setObjectName(_fromUtf8("lblExUtilCount"))

        self.leTitle = QtWidgets.QLineEdit(CalculatePayoff)
        self.leTitle.setGeometry(QtCore.QRect(10, 30, 380, 25))
        self.leTitle.setSizePolicy(sizePolicy)
        self.leTitle.setObjectName(_fromUtf8("leTitle"))

        self.leUnitPrice = QtWidgets.QLineEdit(CalculatePayoff)
        self.leUnitPrice.setGeometry(QtCore.QRect(10, 80, 150, 25))
        self.leUnitPrice.setSizePolicy(sizePolicy)
        self.leUnitPrice.setObjectName(_fromUtf8("leUnitPrice"))

        self.leThreshold = QtWidgets.QLineEdit(CalculatePayoff)
        self.leThreshold.setGeometry(QtCore.QRect(220, 80, 150, 25))
        self.leThreshold.setSizePolicy(sizePolicy)
        self.leThreshold.setObjectName(_fromUtf8("leThreshold"))

        self.btnCheck = QtWidgets.QPushButton(CalculatePayoff)
        self.btnCheck.setGeometry(QtCore.QRect(10, 413, 75, 23))
        self.btnCheck.setSizePolicy(sizePolicy)
        #self.btnCheck.setFont(QtGui.QFont("",pointSize=8))
        self.btnCheck.setText(_fromUtf8("Anwählen"))
        self.btnCheck.setObjectName(_fromUtf8("btnCheck"))
        self.btnCheck.setEnabled(False)

        self.btnClear = QtWidgets.QPushButton(CalculatePayoff)
        self.btnClear.setGeometry(QtCore.QRect(93, 413, 75, 23))
        self.btnClear.setSizePolicy(sizePolicy)
        #self.btnClear.setFont(QtGui.QFont("",pointSize=8))
        self.btnClear.setText(_fromUtf8("Leeren"))
        self.btnClear.setObjectName(_fromUtf8("btnClear"))

        self.DialogBB.accepted.connect(CalculatePayoff.accept)
        self.DialogBB.rejected.connect(CalculatePayoff.reject)
        self.listExUtil.itemChanged.connect(self.itemChanged)
        self.listExUtil.itemSelectionChanged.connect(self.itmSelChanged)
        self.btnCheck.clicked.connect(self.checkSelected)
        self.btnClear.clicked.connect(self.clear)

        QtCore.QMetaObject.connectSlotsByName(CalculatePayoff)

    def varInit(self):
        """init all relevant variables"""
        self.exUtilisationText = []                                                                                                                             # text list of all utilization to be exclude
        self.exUtilisationData = []                                                                                                                             # data list of all utilization to be exclude
        self.listExUtilBitmap = []                                                                                                                              # boolean bitmap list of all utilization to be exclude
        self.docTitle = ""
        self.unitPrice = 0
        self.payoffThreshold = 0

    def itemChanged(self, itm):
        """A list item changed => get checked state and update bitmap and counter"""
        self.itmSelChanged()                                                                                                                                    # update ui (enable or disable buttons)
        self.listExUtilBitmap[itm.data(4)] = bool(itm.checkState())                                                                                             # update the utilization is checked bitmap
        self.lblExUtilCount.setText(_fromUtf8("%4d of %4d" % (sum(self.listExUtilBitmap), len(self.listExUtilBitmap))))                                         # update the ui checked counter

    def clear(self):
        """clear all form entries"""
        self.leTitle.setText("")
        self.leUnitPrice.setText("")
        self.leThreshold.setText("")

        lExUtil = [self.listExUtil.item(it) for it in range(self.listExUtil.count()) if self.listExUtil.item(it).checkState()]                                  # get checked utilizations
        for itm in lExUtil:                                                                                                                                     # uncheck all checked utilizations
            itm.setCheckState(QtCore.Qt.Unchecked)
        for itm in self.listExUtil.selectedItems():                                                                                                             # deselect all selected listview items
            itm.setSelected(False)

        self.varInit()                                                                                                                                          # reset variables

    def checkSelected(self):
        """check all selected items"""
        selExUtilItms = self.listExUtil.selectedItems()
        for itm in selExUtilItms:
            itm.setCheckState(QtCore.Qt.Checked)
        self.btnCheck.setEnabled(False)

    def itmSelChanged(self):
        """enable 'check'-button in case there is a selected item in the listview  which is not yet checked """
        selExUtilItms = self.listExUtil.selectedItems()
        lExUtil = [itm for itm in selExUtilItms if not itm.checkState()]                                                                                        # list odf selected and uncheked items
        self.btnCheck.setEnabled((len(lExUtil) > 0))

    def loadList(self, dictList, textAtt, dataAtt, storedExList):
        """init the listview"""
        self.varInit()                                                                                                                                          # rest the vraiables in case this object is reused
        self.listExUtil.clear()                                                                                                                                 # clear the listview in case this object is reused

        for c, data in enumerate(dictList):                                                                                                                     # enumerate the list of dictionaries and set the datafield and textfield of the listview item according the function parameters
            item = QtWidgets.QListWidgetItem()
            item.setData(3, data)                                                                                                                               # datafield number three is the first empty field of the listview item => store the underlying data
            item.setData(4, c)                                                                                                                                  # store the respective bitmap index
            item.setText(_fromUtf8(data[textAtt]))
            item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
            self.listExUtil.addItem(item)

            checked = (data[dataAtt] in storedExList)                                                                                                           # reload checked state from stored list
            self.listExUtilBitmap.append(checked)
            if checked:
                item.setCheckState(QtCore.Qt.Checked)
            else:
                item.setCheckState(QtCore.Qt.Unchecked)

    def reject(self):
        """rejected dialog result"""
        self.Rejected = 1
        self.Accepted = 0
        self.done(0)

    def accept(self):
        """accepted dialog result"""
        for it in range(self.listExUtil.count()):                                                                                                               # create list of selected utilizations for exclusion
            itm = self.listExUtil.item(it)
            if(itm.checkState()):
                self.exUtilisationText.append(itm.text())                                                                                                       # text only list
                self.exUtilisationData.append(itm.data(3))                                                                                                      # complete utilization data list

        self.docTitle = self.leTitle.text()                                                                                                                     # set the documenz title from the title entry

        if(len(self.leUnitPrice.text()) == 0):                                                                                                                  # set the unit price from the entry replace comma with point
            self.unitPrice = 0
        else:
            self.unitPrice = float(self.leUnitPrice.text().replace(',', '.'))

        if(len(self.leThreshold.text()) == 0):                                                                                                                  # set the payoff threshold from the entry replace comma with point
            self.payoffThreshold = 0
        else:
            self.payoffThreshold = float(self.leThreshold.text().replace(',', '.'))

        self.Rejected = 0
        self.Accepted = 1
        self.done(1)


class ParcelsOwner(object):
    """represents a legal entity that owns shares of parcels"""
    def __init__(self, nameList, listType=None):
        """namelist: list of name information => only one entry in case of a natural person or organisation
           listType: str => None in case of natural person or organisation or the name of the description of the legal entity
        """
        self.ownerNames = nameList
        self.ownerGroup = listType
        self.filterName = self.GetFilterName()                                                                                                                  # string key uset to sort the ParcelsOwner objects
        self.strID = hash(",".join(nameList))                                                                                                                   # get an id by calculation the hash of the owner name fragments
        self.sharedParcelsHolds = []                                                                                                                            # ParcelShare instances; there can be multiple instances for the same parcel in case multiple holdings exist

    @property
    def gSurUnPacOwn(self):
        """get the total huntable area for this parcel share owner"""
        return self.CalcGSUnPacified()                     # Calculate pacified surface

    def CalcGSUnPacified(self):
        """calculate the total huntable area by adding together owner area share for
        every parcel share of the owner"""
        sur = 0
        for s in self.sharedParcelsHolds:
            sur += s.surTotUnPacPartOwn
        return sur

    def CalcPayoffFract(self, payoffPerm2):
        """calculate the owner payoff based on the total huntable area
        and the price per square meter"""
        return round(payoffPerm2 * self.gSurUnPacOwn, 2)                                                                                                        # two digit accuracy

    def PayoffYesNo(self, thres, value):
        """is the payoff threshold reached"""
        return (value >= thres)

    def GetFilterName(self):
        """get the filter str key to filter the owners"""
        if self.ownerGroup is not None:                                                                                                                         # in case the owner constist of multiple owners return the owner group string
            return self.ownerGroup
        else:
            sSplit = self.ownerNames[0].split(';')
            return sSplit[2]                                                                                                                                    # otherwise return the surname

    def GetStreets(self):
        """get list of street names for all parcel shares"""
        sharedParcels = set([(ph.flsnr, ph.street) for ph in self.sharedParcelsHolds])                                                                          # get unique set from shared parcel holdings reduced to the parcels identifier and strret names

        aString = ""
        strs = [s[1] for s in sharedParcels if len(s[1]) > 0]                                                                                                   # get list pf street names
        counts = Counter(strs)                                                                                                                                  # count all street names

        for s in counts.keys():
            if(counts[s] > 1):
                aString += s + " " + str(counts[s]) + "x\n"                                                                                                     # add strret name and count in line string
            else:
                aString += s + "\n"
        return aString

    def GetParcelCount(self):
        """get count of unique parcels"""
        uniqueIds = np.unique(np.array([ph.flsnr for ph in self.sharedParcelsHolds]))                                                                           # get unique parcel ids from all holding shares
        return len(uniqueIds)


class ParcelShare(object):
    """is a share of a parcel"""
    def __init__(self, queryData, utilisationExclusion, holdingShare, ownerShare):
        """queryData: dictonary containing the parcel share data
           utilisationExclusion: list of all utilization that are ignored in the calculation
        """
        self.utilEx = utilisationExclusion                                                                                                                      # utilizations that need to be excluded
        self.flsnr = queryData['flsnr']                                                                                                                         # parcel number
        self.share = self.StringFraction(holdingShare) * self.StringFraction(ownerShare)                                                                        # parcel share by holding share and owner share
        self.surTot = float(queryData['tSur'])                                                                                                                  # total parcel area
        self.utilsSurList = queryData['utilSur']                                                                                                                # tuple(utilisation, area)
        self.street = queryData['str']                                                                                                                          # combinded parcel streets string
        self.surTotUnPac, self.surTotPac = self.CalcSUnPacPac()                                                                                                 # huntable and not huntable part of the area
        self.surTotUnPacPartOwn = round(self.surTotUnPac * self.share, 1)                                                                                       # share of the total huntable area of the owner
        self.valid = self.PlausibilityCheck()                                                                                                                   # do a basic plausibilizy check on the calculation

    def PlausibilityCheck(self):
        """basic plausibility check
        the utilization areas added should be equal the total surface
        and the huntable area must be less or equal the total surface
        there is a tolerance of one square metre becuase of rounded values in the dataset"""
        tSur = 0                                                                                                                                                # total area
        for s in self.utilsSurList:
            tSur += float(s['sur'])
        return abs(tSur - self.surTot) <= 1 and self.surTotUnPac <= (self.surTot + 1)                                                                           # with tolerance

    def CalcSUnPacPac(self):
        """calculation of the huntable and not huntable part of the area"""
        unpSur = 0                                                                                                                                              # unpacified area
        pSur = 0                                                                                                                                                # pacified area
        for s in self.utilsSurList:                                                                                                                             # add the utilization area to unpacified in case utilization is not in exclusion list
            if s['util'] not in self.utilEx:
                unpSur += float(s['sur'])
            else:
                pSur += float(s['sur'])
        return unpSur, pSur                                                                                                                                     # return unpacified and pacified area tuple

    def StringFraction(self, strFract):
        """turn the string representation of a fraction to a float"""
        return ParcelShare.StringFractionStatic(strFract)

    @staticmethod
    def StringFractionStatic(strFract):
        """turn the string representation of a fraction to a float"""
        if strFract == '':                                                                                                                                      # the strFract parameter can be an empty string, in this case the parcel share for the onwer is not explictly set and for holdings is 1
            return 1

        tsplit = strFract.split('/')
        if (len(tsplit) != 2):                                                                                                                                  # in case the string is not a fraction string return an error
            QMessageBox.critical(None, "Fehler",
                                 u"Grundstücksanteil konnte nicht bestimmt werden. Die Anteilsangabe ist %s\n Der Anteil wird in der Kalkulation nicht berücksichtigt" % strFract)
        else:
            return round(float(tsplit[0]) / float(tsplit[1]), 5)

    @staticmethod
    def SharesCheckStatic(shares):
        """the sum of all shares should be equal to 1 (with tolerance)
        or in case she share is not explicitly set all values must be equal
        """
        shareSum = np.sum(np.array(shares))
        if mt.isclose(shareSum, 1, rel_tol=0.005):                                                                                                              # 0.5% tolerance to a share equal 1
            return (True, True)                                                                                                                                 # is explicit, is in tolerance
        elif shareSum > 1:                                                                                                                                      # in case share is not explicitly set all shares must be the same value
            return (False, all([True for n in shares if n == shares[0]]))                                                                                       # is explicit, is valid
        else:
            return (False, False)                                                                                                                               # shareSum is invalid


#######################################################
# UtilizationsUI (shows parcel utilizations as html content dialog)
#######################################################
class UtilizationsUI(QDialog):
    """shows parcel utilizations as html content dialog"""
    def __init__(self, data):
        """Constructor.

        :param data: the data to be converted to html
        :type data: (list, int) list of utilization dict and int for the total parcel count
        """
        QDialog.__init__(self)
        self.setupUi(self)
        self.tbhtml.setHtml(self.toHTML(data))                                                                                                                 # convert the init data to a html string

    def setupUi(self, HuntReg):
        """init dialog UI"""
        HuntReg.setObjectName(_fromUtf8("HuntReg"))
        HuntReg.setWindowModality(QtCore.Qt.WindowModal)
        HuntReg.resize(900, 800)
        HuntReg.setWindowTitle(_fromUtf8("Flächennutzung"))

        self.horizontalLayout = QtWidgets.QHBoxLayout(HuntReg)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        self.tbhtml = QtWidgets.QTextBrowser(HuntReg)
        self.tbhtml.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.tbhtml.setGeometry(QtCore.QRect(5, 5, 890, 790))
        self.tbhtml.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        self.tbhtml.setProperty("url", QtCore.QUrl(_fromUtf8("about:blank")))
        self.tbhtml.setObjectName(_fromUtf8("tbhtml"))
        self.horizontalLayout.addWidget(self.tbhtml)

    def print_(self):
        """shows printer dialog for html content"""
        printer = QPrinter()
        dlg = QPrintDialog(printer)
        if dlg.exec_() == QDialog.Accepted:
            self.tbhtml.print_(printer)

    def contextMenuEvent(self, e):
        """add contect menu event"""
        menu = QtWidgets.QMenu(self)
        action = QtWidgets.QAction("Drucken", self)
        action.triggered.connect(self.print_)
        menu.addAction(action)
        menu.exec_(e.globalPos())

    def toHTML(self, data):
        """create html from utilization data list"""
        (utils, parcelcount) = data                                                                                                                         # seperate data to util dictionary and total parcel count
        listUtilSumm = []                                                                                                                                   # list of utilization summary instances
        listUtilKey = []                                                                                                                                    # list of the utilization keys

        for util in utils:                                                                                                                                  # enumerate utilizations of all parcels
            ind = -1
            if util['nutzsl'] in listUtilKey:                                                                                                               # in case the key is already known => append, otherwise create new utilization summary instance and key
                ind = listUtilKey.index(util['nutzsl'])                                                                                                     # get index of utilsummary instance
            if ind == -1:
                listUtilSumm.append(UtilSummary(util))
                listUtilKey.append(util['nutzsl'])
            else:
                listUtilSumm[ind].Update(util)

        listUtilSumm.sort(key=lambda x: x.uName, reverse=False)                                                                                             # sort the utilzations according the utilization name
        totalSur = 0
        for utilObj in listUtilSumm:                                                                                                                        # calculate the total are based on all utilization areas
            totalSur += utilObj.surTot

        headData = dict([('title', u"Fl\xe4chennutzung"), ('countfl', parcelcount), ('countutil', len(listUtilSumm)),                                       # turn the basic data to a dictionary usable for the html string
                        ('surtotm2', totalSur), ('surtotha', round(totalSur / 10000, 2)), ('date', QDate.currentDate().toString("d. MMMM yyyy"))])
        html = u"""
        <HTML xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<style>
.fls_tab{width:100%%;empty-cells:show}
.fls_time{text-align:right;width:100%%}
.fls_headline_col{background-color:#EEEEEE;width:100%%;height:30px;text-align:center;}
.fls_headline{font-weight:bold;font-size:24px;}
.fls_col_names{font-weight:bold;}
.fls_col_values{vertical-align:top;}
.fls_bst{width:100%%;empty-cells:show}
.fls_hr{border:dotted 1px;color:#080808;}
.fls_footnote{text-align:center;}
</style>

<table class="fls_tab" width="100%%">
<tbody>
<tr style="height: 18px;">
<td style="width: 50%%; height: 18px;" colspan="5">Jagdkataster</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(date)s</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr class="fls_headline_col" style="height: 18px;">
<td style="width: 100%%; text-align: center; height: 18px;" colspan="10"><span class="fls_headline">%(title)s</span></td>
</tr>
<tr style="height: 18px;">
<td style="width: 100%%; height: 18px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Anzahl Flurst&uuml;cke:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(countfl)s</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Anzahl Nutzungen:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(countutil)s</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Gesamtfl&auml;che in m&sup2;:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(surtotm2)s m&sup2;</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Gesamtfl&auml;che in ha:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(surtotha)s ha</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 18px;">
<td style="width: 100%%; height: 18px;" colspan="10">
<h3>Nutzungen</h3>
</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr class="fls_col_names" style="height: 18px;">
<td style="width: 60%%; height: 18px;" colspan="6">Nutzung</td>
<td style="width: 5%%; height: 18px; text-align: right;">FlurAnz.</td>
<td style="width: 20%%; height: 18px; text-align: right;">Fl&auml;che m&sup2;</td>
<td style="width: 15%%; height: 18px; text-align: right;">Fl&auml;che ha</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
    """ % headData

        utildata = dict()                                                                                                                                   # turn UtilizationSummary instance data to a dictionary for the html string
        for util in listUtilSumm:
            utildata['nutzung'] = util.uName
            utildata['pc'] = util.parcelCount
            utildata['surm2'] = util.surTot
            utildata['surha'] = util.surTotHa

            html += u"""
<tr style="height: 16px;">
<td style="width: 60%%; height: 16px;" colspan="6">%(nutzung)s</td>
<td style="width: 5%%; height: 16px; text-align: right;">%(pc)s</td>
<td style="width: 20%%; height: 16px; text-align: right;">%(surm2)s m&sup2;</td>
<td style="width: 15%%; height: 16px; text-align: right;">%(surha)s ha</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
""" % utildata

        html += u"""
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 18px;">
<td style="width: 50%%; height: 18px;" colspan="5">Jagdkataster</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(date)s</td>
</tr>
""" % headData
        html += u"""
</tbody>
</table>
"""
        return html


#######################################################
# ParcelsCertsUI (shows parcel certs as html content dialog)
#######################################################
class ParcelsCertsUI(QDialog):
    """shows parcel certs as html content dialog"""
    def __init__(self, data, title=None):
        """Constructor.

        :param data: the data to be converted to html
        :type data: list of dict
        """
        QDialog.__init__(self)
        self.title = title                                                                                                                                      # optional diffferent title for dialog
        self.setupUi(self)
        self.tbhtml.setHtml(self.toHTML(data))                                                                                                                  # convert the init data to a html string

    def setupUi(self, HuntReg):
        """init dialog UI"""
        HuntReg.setObjectName(_fromUtf8("HuntReg"))
        HuntReg.setWindowModality(QtCore.Qt.WindowModal)
        HuntReg.resize(1000, 800)

        if self.title is None:
            HuntReg.setWindowTitle(_fromUtf8("Flurstückzertifikate"))
        else:
            HuntReg.setWindowTitle(_fromUtf8(self.title))

        self.horizontalLayout = QtWidgets.QHBoxLayout(HuntReg)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        self.tbhtml = QtWidgets.QTextBrowser(HuntReg)
        self.tbhtml.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.tbhtml.setGeometry(QtCore.QRect(5, 5, 990, 790))
        self.tbhtml.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        self.tbhtml.setProperty("url", QtCore.QUrl(_fromUtf8("about:blank")))
        self.tbhtml.setObjectName(_fromUtf8("tbhtml"))
        self.horizontalLayout.addWidget(self.tbhtml)

    def print_(self):
        """shows printer dialog for html content"""
        printer = QPrinter()
        dlg = QPrintDialog(printer)
        if dlg.exec_() == QDialog.Accepted:
            self.tbhtml.print_(printer)

    def contextMenuEvent(self, e):
        """add contect menu event"""
        menu = QtWidgets.QMenu(self)
        action = QtWidgets.QAction("Drucken", self)
        action.triggered.connect(self.print_)
        menu.addAction(action)
        menu.exec_(e.globalPos())

    def toHTML(self, data):
        """create html from utilization data list"""

        html = u"""
<HTML xmlns="http://www.w3.org/1999/xhtml">
  <HEAD>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </HEAD>
  <BODY>
"""
        for res in data:                                                                                                                                        # generate the html certificate for each data entity
            html += self.singleCertBody(res)
        html += u"""
</BODY>
</HTML>
"""
        return html

    def singleCertBody(self, res):
        """return a single html cert body without header
        html code is derived from alkisplugin"""

        html = u"""
<TABLE style="width:100%%;empty-cells:show" border="0" width="100%%" cellspacing="0">
    <TR style="font-weight:bold;font-size:12px;">
        <TD colspan="3" style="background-color:#EEEEEE;width:100%%;height:30px;text-align:left;">Flurst&uuml;cksnachweis</TD><TD style="background-color:#EEEEEE;font-weight:bold;font-size:10px;text-align:right;width:100%%" colspan="4" align="right">%(date)s</TD></TR>
    </TR>
    <TR><TD colspan="7">&nbsp;</TD></TR>
    <TR>
        <TD colspan="7"><h3>Flurst&uuml;ck %(gemashl)s-%(flr)s-%(flsnrk)s<hr style="width:100%%"></h3></TD>
    </TR>
    <TR style="font-weight:bold">
        <TD width="15%%">Gemarkung</TD>
        <TD width="6%%">Flur</TD>
        <TD width="15%%">Flurst&uuml;ck</TD>
        <TD width="20%%">Flurkarte</TD>
        <TD width="17%%">Entstehung</TD>
        <TD width="17%%">Fortf&uuml;hrung</TD>
        <TD width="5%%">Fl&auml;che</TD>
    </TR>
    <TR style="vertical-align:top;font-size:10px;">
        <TD>%(gemashl)s<br>%(gemarkung)s</TD>
        <TD>%(flr)s</TD>
        <TD>%(flsnrk)s</TD>
        <TD>%(flurknr)s</TD>
        <TD>%(entst)s</TD>
        <TD>%(fortf)s</TD>
        <TD>%(flsfl)s&nbsp;m&sup2;</TD>
    </TR>
</TABLE>
""" % res

        if res['blbnr']:
            html += u"""
<TABLE style="width:100%%;empty-cells:show" border="0" width="100%%">
    <TR style="font-weight:bold">
        <TD width="21%%"></TD>
        <TD width="79%%">Baulastenblattnr.</TD>
    </TR>
    <TR style="vertical-align:top;font-size:10px;">
        <TD></TD>
        <TD>%(blbnr)s</TD>
    </TR>
</TABLE>
""" % res

        if res['lagebez'] or res['anl_verm']:
            html += u"""
<TABLE style="width:100%%;empty-cells:show" border="0" width="100%%">
    <TR style="font-weight:bold">
        <TD width="21%%"></TD>
        <TD width="52%%">Lage</TD>
        <TD width="27%%">Anliegervermerk</TD>
    </TR>
    <TR style="vertical-align:top;font-size:10px;">
        <TD></TD>
        <TD>%(lagebez)s</TD>
        <TD>%(anl_verm)s</TD>
    </TR>
</TABLE>
""" % res

        if 'str' in res:
            if res['str']:
                html += u"""
<TABLE border="0" style="width:100%%;empty-cells:show" width="100%">
    <TR style="font-weight:bold">
        <TD width="21%"></TD>
        <TD width="52%">Strasse</TD>
        <TD width="27%">Hausnummer</TD>
    </TR>
"""

                for strres in res['str']:
                    html += u"""
    <TR style="vertical-align:top;font-size:10px;">
        <TD></TD><TD>%(strname)s</TD><TD>%(hausnr)s</TD></TR>
    </TR>
""" % strres

                html += u"""
</TABLE>
"""

        if 'nutz' in res:
            html += u"""
<TABLE border="0" style="width:100%%;empty-cells:show" width="100%">
        <TR style="font-weight:bold"><TD width="21%"></TD><TD width="69%">Nutzung</TD><TD width="10%">Fl&auml;che</TD></TR>
"""
            if res['nutz']:
                for nutz in res['nutz']:
                    html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD>21%(nutzshl)s - %(nutzung)s</TD><TD>%(fl)s&nbsp;m&sup2;</TD></TR>
""" % nutz
            else:
                html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD colspan=2>Keine</TD></TR>
"""

        html += u"""
</TABLE>
"""

        if 'klas' in res:
            html += u"""
<TABLE border="0" style="width:100%%;empty-cells:show" width="100%">
        <TR style="font-weight:bold"><TD width="21%"></TD><TD width="69%">Klassifizierung(en)</TD><TD width="10%">Fl&auml;che</TD></TR>
"""

            if res['klas']:
                for klas in res['klas']:
                    html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD>%(klf_text)s</TD><TD>%(fl)s&nbsp;m&sup2;</TD></TR>
""" % klas
            else:
                html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD colspan=2>Keine</TD></TR>
"""

        html += u"""
</TABLE>
"""

        if 'afst' in res:
            html += u"""
<TABLE border="0" style="width:100%%;empty-cells:show" width="100%">
        <TR style="font-weight:bold"><TD width="21%"></TD><TD width="79%">Ausf&uuml;hrende Stelle(n)</TD></TR>
"""

            if res['afst']:
                for afst in res['afst']:
                    html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD>%(afst_txt)s</TD></TR>
""" % afst

            else:
                html += u"""
        <TR style="vertical-align:top;font-size:10px;"><TD></TD><TD colspan=2>Keine</TD></TR>
"""

            html += u"""
</TABLE>
"""

        if 'best' in res:
            if res['best']:
                html += u"""
<br>
<TABLE border="0" style="width:100%%;empty-cells:show" width="100%">
        <TR><TD colspan="6"><h3>Best&auml;nde<hr style="width:100%"></h3></TD></TR>
"""

                for best in res['best']:
                    html += u"""
        <TR style="font-weight:bold">
                <TD>Bestandsnummer</TD>
                <TD>Grundbuchbezirk</TD>
                <TD colspan="2">Grundbuchblattnr.</TD>
                <TD>Anteil</TD>
        </TR>
        <TR style="vertical-align:top;font-size:10px;">
                <TD>%(bestdnr)s</TD>
                <TD>%(gbbz)s</TD>
                <TD colspan="2">%(gbblnr)s</TD>
                <TD>%(anteil)s</TD>
        </TR>
        <TR style="font-weight:bold">
                <TD></TD>
                <TD>Buchungskennz.</TD>
                <TD>BVNR</TD>
                <TD>PZ</TD>
""" % best

                    if res['hist']:
                        html += u"""
                <TD>Hist. Bestand</TD><TD>Hist. Zuordnung</TD>
"""
                    else:
                        html += u"""
                <TD></TD><TD></TD>
"""

                    html += u"""
        </TR>
        <TR style="vertical-align:top;font-size:10px;">
                <TD></TD>
                <TD>%(eignerart)s</TD>
                <TD>%(bvnr)s</TD>
                <TD>%(pz)s</TD>
""" % best

                    html += "<TD>%s</TD>" % ("ja" if res['hist'] and best['bhist'] else "")
                    html += "<TD>%s</TD>" % ("ja" if res['hist'] and best['zhist'] else "")

                    html += u"""
        </TR>
"""

                    if 'bse' in best:
                        if best['bse']:
                            html += u"""
        <TR style="font-weight:bold"><TD>Anteil</TD><TD colspan="5">Namensinformation</TD></TR>
"""

                            for bse in best['bse']:
                                html += u"""
        <TR style="vertical-align:top;font-size:10px;">
                <TD>%(antverh)s</TD>
                <TD colspan="5">%(name1)s %(name2)s<br>%(name3)s<br>%(name4)s</TD>
        </TR>
""" % bse
                        else:
                            html += u"""
        <p>Kein Eigentümer gefunden.</p>
"""

                        html += u"""
        <TR><TD colspan="6"><hr style="border:dotted 1px;color:#080808;"></TD></TR>
"""

        html += u"""
        <TR><TD colspan="6">&nbsp;</TD></TR>
        </TABLE>
"""
        return html


#######################################################
# HuntRegUI (shows hunt register as html content dialog)
#######################################################
class HuntRegUI(QDialog):
    """shows hunt register as html content dialog"""
    def __init__(self, data):
        """Constructor.

        :param data: the data to be converted to html
        :type data: dict
        """
        QDialog.__init__(self)
        self.setupUi(self)
        self.data = data                                                                                                                                        # store the initial dat for further processing
        self.tbhtml.setHtml(self.toHTML(data))                                                                                                                  # convert the initialization dataset to a html representation

    def setupUi(self, HuntReg):
        """init dialog UI"""
        HuntReg.setObjectName(_fromUtf8("HuntReg"))
        HuntReg.setWindowModality(QtCore.Qt.WindowModal)
        HuntReg.resize(1200, 800)
        HuntReg.setWindowTitle(_fromUtf8("Jagdkataster"))

        self.horizontalLayout = QtWidgets.QHBoxLayout(HuntReg)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))

        self.tbhtml = QtWidgets.QTextBrowser(HuntReg)
        self.tbhtml.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
        self.tbhtml.setGeometry(QtCore.QRect(5, 5, 1190, 790))
        self.tbhtml.setLocale(QtCore.QLocale(QtCore.QLocale.English, QtCore.QLocale.UnitedKingdom))
        self.tbhtml.setProperty("url", QtCore.QUrl(_fromUtf8("about:blank")))
        self.tbhtml.setObjectName(_fromUtf8("tbhtml"))
        self.horizontalLayout.addWidget(self.tbhtml)

    def print_(self):
        """shows printer dialog for html content"""
        printer = QPrinter()
        dlg = QPrintDialog(printer)
        if dlg.exec_() == QDialog.Accepted:
            self.tbhtml.print_(printer)

    def csv_(self):
        """shows printer dialog for html content"""
        csvfile, *_ = QFileDialog.getSaveFileName(filter="*.csv")                                                                                               # get the absolute path with file name and type from the save file dialog

        if not csvfile:                                                                                                                                         # the path is empty in case the user cancels the dialog
            return

        entryData = self.data['entryData']                                                                                                                      # the data the user entered into the form
        totalUnPacSur = self.data['totalUnPacSur']                                                                                                              # the total huntable surface of all selected parcels
        parcelOwnerList = self.data['procLists']['pol']                                                                                                         # list of all parcel owner instances derived from the selected parcels
        totalmoney = round(totalUnPacSur * entryData['unitPrice'], 2)                                                                                           # the total payoff money in case the total huntable surface is paid off

        date = QDate.currentDate().toString("d. MMMM yyyy")                                                                                                     # current date
        header = (u"CSV {} vom {}\n"                                                                                                                            # generate a single header string for csv
                  u"Auszahlungsbetrag pro Quadratmeter: {} Euro\n"
                  u"Auszahlungsschwellwert: {} Euro\n"
                  u"unbef. Gesamtfläche: {} Quadratmeter\n"
                  u"Gesamtbetrag: {} Euro\n"
                  .format(entryData['docTitle'], date, entryData['unitPrice'], entryData['payThresh'], round(totalUnPacSur, 1), totalmoney))

        colheads = ["Eigner", "Lage", "FlurAnz", "unb. Fläche", "Betrag", "Ausz."]                                                                              # generate a column head for the csv columns
        parcelOwnerList.sort(key=lambda x: x.filterName, reverse=False)                                                                                         # filter all parcel pacerl owners according to the filter name

        try:
            with open(csvfile, 'w', encoding='iso-8859-1') as outfile:                                                                                          # open or create the csv file, encode it for western europe, with this encodeing microsoft excel can open and display the data properly
                # write total header and column header
                outfile.write(u"\"{}\"".format(header) + '\n')
                outfile.write(','.join(h for h in colheads) + '\n')
                # write data
                for owner in parcelOwnerList:                                                                                                                   # enumerate parcel owners
                    onames = self.processNames(owner.ownerNames, owner.ownerGroup)                                                                              # join all owner names to a single string
                    streets = owner.GetStreets()                                                                                                                # get the string representation for the parcel streets
                    pc = owner.GetParcelCount()                                                                                                                 # get the parcel count for the owner
                    unparea = round(owner.gSurUnPacOwn, 1)                                                                                                      # get the owners total huntable area for all parcel shares
                    value = owner.CalcPayoffFract(entryData['unitPrice'])                                                                                       # calculate the owners pay off value according to the square metre unit price
                    if(owner.PayoffYesNo(entryData['payThresh'], value)):                                                                                       # indicator string if the pay off treshold is reached
                        pay = "Ja"
                    else:
                        pay = "Nein"

                    cells = [onames, streets, pc, unparea, value, pay]
                    outfile.write(','.join(u"\"{}\"".format(c) for c in cells) + '\n')                                                                          # get csv line string for all cells
        except PermissionError:
            QMessageBox.critical(None, "Fehler", u"Überschreiben verweigert. Ist die Datei geöffnet?")

    def contextMenuEvent(self, e):
        """add contect menu event"""
        menu = QtWidgets.QMenu(self)
        printaction = QtWidgets.QAction("Drucken", self)
        printaction.triggered.connect(self.print_)
        csvaction = QtWidgets.QAction("CSV", self)
        csvaction.triggered.connect(self.csv_)
        menu.addAction(printaction)
        menu.addAction(csvaction)
        menu.exec_(e.globalPos())

    def processNames(self, names, nameType):
        """convert owner names to a single string representation"""
        aString = ""
        if(nameType is not None):
            aString += nameType + "\n"                                                                                                                          # in case lega entity is not a single entity start the string with the entity type

        for n in names:
            sp = n.split(';')                                                                                                                                   # split the enitity name line
            fl = list(filter(lambda a: a != '', sp))                                                                                                            # some fields may not be present, return only valid filled fields

            lineString = ""
            if fl:
                for s in fl:
                    if s[0] != '(' or len(names) == 1:                                                                                                          # add a single owner name
                        lineString += s + " "
                if(len(lineString) > 0):
                    aString += lineString + "\n"
        return aString

    def toHTML(self, data):
        """create html from data dict"""
        entryData = data['entryData']                                                                                                                           # the data the user entered into the form
        totalUnPacSur = data['totalUnPacSur']                                                                                                                   # the total huntable surface of all selected parcels
        parcelOwnerList = data['procLists']['pol']                                                                                                              # list of all parcel owner instances derived from the selected parcels

        headData = dict([('title', entryData['docTitle']), ('threshold', entryData['payThresh']), ('moneypunit', entryData['unitPrice']), ('unpacsur', round(totalUnPacSur, 1)), ('totalmoney', round(totalUnPacSur * entryData['unitPrice'], 2))])
        headData['date'] = QDate.currentDate().toString("d. MMMM yyyy")                                                                                         # header dictionary for use in html string
        parcelOwnerList.sort(key=lambda x: x.filterName, reverse=False)                                                                                         # filter all parcel pacerl owners according to the filter name

        html = u"""
        <HTML xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<style>
.fls_tab{width:100%%;empty-cells:show}
.fls_time{text-align:right;width:100%%}
.fls_headline_col{background-color:#EEEEEE;width:100%%;height:30px;text-align:center;}
.fls_headline{font-weight:bold;font-size:24px;}
.fls_col_names{font-weight:bold;}
.fls_col_values{vertical-align:top;}
.fls_bst{width:100%%;empty-cells:show}
.fls_hr{border:dotted 1px;color:#080808;}
.fls_footnote{text-align:center;}
</style>

<table class="fls_tab" width="100%%">
<tbody>
<tr style="height: 18px;">
<td style="width: 50%%; height: 18px;" colspan="5">Jagdkataster</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(date)s</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr class="fls_headline_col" style="height: 18px;">
<td style="width: 100%%; text-align: center; height: 18px;" colspan="10"><span class="fls_headline">%(title)s</span></td>
</tr>
<tr style="height: 18px;">
<td style="width: 100%%; height: 18px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Auszahlungsbetrag pro m&sup2;:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(moneypunit)s &euro;&#47;m&sup2;</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Auszahlungsschwellwert:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(threshold)s &euro;</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">unbef. Gesamtfl&auml;che:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(unpacsur)s m&sup2;</td>
</tr>
<tr style="height: 22px;">
<td style="width: 50%%; height: 18px;" colspan="5">Gesamtbetrag:</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(totalmoney)s &euro;</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 18px;">
<td style="width: 100%%; height: 18px;" colspan="10">
<h3>Eigner Zusammenfassung</h3>
</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
<tr class="fls_col_names" style="height: 18px;">
<td style="width: 50%%; height: 18px;" colspan="5">Eigner</td>
<td style="width: 20%%; height: 18px; text-align: right;">Lage</td>
<td style="width: 5%%; height: 18px; text-align: right;">FlurAnz.</td>
<td style="width: 10%%; height: 18px; text-align: right;">unb. Fl&auml;che</td>
<td style="width: 10%%; height: 18px; text-align: right;">Betrag</td>
<td style="width: 5%%; height: 18px; text-align: right;">Ausz.</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
        """ % headData

        ownersum = dict()
        for owner in parcelOwnerList:
            ownersum['onames'] = "<pre>{}</pre>".format(self.processNames(owner.ownerNames, owner.ownerGroup))                                                  # join all owner names to a single string
            ownersum['streets'] = "<pre>{}</pre>".format(owner.GetStreets())                                                                                    # get the string representation for the parcel streets
            ownersum['pc'] = owner.GetParcelCount()                                                                                                             # get the parcel count for the owner
            ownersum['unparea'] = round(owner.gSurUnPacOwn, 1)                                                                                                  # get the owners total huntable area for all parcel shares
            ownersum['value'] = owner.CalcPayoffFract(entryData['unitPrice'])                                                                                   # calculate the owners pay off value according to the square metre unit price
            if(owner.PayoffYesNo(entryData['payThresh'], ownersum['value'])):                                                                                   # indicator string if the pay off treshold is reached
                ownersum['pay'] = "Ja"
            else:
                ownersum['pay'] = "Nein"

            html += u"""
<tr style="height: 16px;">
<td style="width: 50%%; height: 16px;" colspan="5">%(onames)s</td>
<td style="width: 20%%; height: 16px; text-align: right;">%(streets)s</td>
<td style="width: 5%%; height: 16px; text-align: right;">%(pc)s</td>
<td style="width: 10%%; height: 16px; text-align: right;">%(unparea)s m&sup2;</td>
<td style="width: 10%%; height: 16px; text-align: right;">%(value)s &euro;</td>
<td style="width: 5%%; height: 16px; text-align: right;">%(pay)s</td>
</tr>
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10"><hr style="width: 100%%;" /></td>
</tr>
""" % ownersum

        html += u"""
<tr style="height: 16px;">
<td style="width: 100%%; height: 16px;" colspan="10">&nbsp;</td>
</tr>
<tr style="height: 18px;">
<td style="width: 50%%; height: 18px;" colspan="5">Jagdkataster</td>
<td class="fls_time" style="width: 50%%; height: 18px;" colspan="5" align="right">%(date)s</td>
</tr>
""" % headData
        html += u"""
</tbody>
</table>
"""
        return html
