# -*- coding: utf-8 -*-
"""
/***************************************************************************
 Layer
                                 A QGIS plugin
 wide are mapping
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2022-01-12
        git sha              : $Format:%H$
        copyright            : (C) 2020 by forschung@ciss.de
        email                : forschung@ciss.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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
import os
from abc import abstractmethod, ABC

import xlrd
from qgis.PyQt.QtCore import QVariant
from qgis.core import QgsVectorLayer, QgsField, QgsGeometry, QgsPointXY, QgsFeature

from weissflaechenkartierung.src.qgis import QGisInterface

from weissflaechenkartierung.src.logger import Logger
import weissflaechenkartierung.src.xml.xml_config_ctrl as xml


class LayerMixIn(ABC):
    def __init__(self, xml_section, module):
        """
        :param xml_section: section of an xml dom
        :param module: an module instance
        """
        self._xml_section = xml_section
        self._module = module
        self._parameters = xml.XMLConfigCtrl.get_parameter_from_xml(xml=self._xml_section)
        self._layer = None
        self._clip = False
        self._crs = "EPSG:32832"  # coordinate reference system

    @property
    def parameters(self):
        """
        returns the parameters
        """
        return self._parameters

    @property
    def crs(self):
        """
        returns the crs
        """
        return self._crs

    @property
    def clip(self) -> bool:
        """
        returns the clips value
        """
        return self._clip

    @property
    def layer(self):
        """
        returns the layer of the layer
        """
        return self._layer

    @property
    def xml_section(self):
        """
        returns the xml section
        """
        return self._xml_section

    @abstractmethod
    def create_layer(self):
        """
        abstract method for inheritance
        """
        if "clip" in self._parameters:
            self._clip = xml.XMLConfigCtrl.get_bool_value(value=self._parameters["clip"], default=False)
        if "default_crs" in self._module.config.parameters:
            self._crs = self._module.config.parameters["default_crs"]
        if "crs" in self._parameters:
            self._crs = self._parameters["crs"]
        return True


class ShapeLayer(LayerMixIn):
    def create_layer(self):
        file_path = self._module.connector.connection
        if not os.path.isfile(path=file_path):
            Logger.debug("The given path as a shape layer is not a file: " + file_path)
            raise FileNotFoundError("The given path as a shape layer is not a file: " + file_path)
        super().create_layer()
        Logger.debug("Create ShapeLayer layer", )
        self._layer = QGisInterface.load_shape(url=file_path,
                                               name="tmp",
                                               crs=self._crs)

        if self._clip:
            self._layer = QGisInterface.clip_by_layer(input_layer=self._layer,
                                                      overlay_layer=self._module.config.qgis_layer,
                                                      name_layer="tmp"
                                                      )
            f = file_path.split("\\")
            Logger.debug("clip: " + f[len(f) - 1] + " is true", )
        return True


class EegCsvLayer(LayerMixIn):
    def __init__(self, xml_section, module):
        LayerMixIn.__init__(self, xml_section=xml_section, module=module)

        self._data = []

    @property
    def data(self):
        """
        returns the data
        """
        return self._data

    def create_layer(self):
        file_path = self._module.connector.connection
        if not os.path.isfile(path=file_path):
            Logger.debug("The given path as a shape layer is not a file: " + file_path)
            raise FileNotFoundError("The given path as a shape layer is not a file: " + file_path)
        Logger.debug("Create EegCsvLayer layer", )
        super().create_layer()
        workbook = xlrd.open_workbook(file_path)
        s = workbook.sheet_by_index(0)
        for row in range(1, s.nrows):
            if s.cell_value(row, 9) == "Wind Land" and s.cell_value(row, 22) == "Nordrhein-Westfalen":
                self.data.append(s.row(row))

        vl = QgsVectorLayer("point?crs=" + self.crs, "tmp", "memory")
        pr = vl.dataProvider()
        vl.startEditing()
        pr.addAttributes([QgsField("anlagenschluessel", QVariant.String),  # 3
                          QgsField("netzbetreiber", QVariant.String),  # 31
                          QgsField("gemarkung", QVariant.String)])  # 20
        vl.updateFields()
        for row in self.data:
            try:
                geom = QgsGeometry.fromPointXY(QgsPointXY(row[24].value - 32000000, row[25].value))
                if self.clip and not geom.intersects(self._module.config.layer_geom):
                    continue
            except:
                continue
            fet = QgsFeature()
            fet.setGeometry(geom)
            fet.setAttributes([QVariant(row[3].value), QVariant(row[31].value), QVariant(row[20].value)])
            pr.addFeatures([fet])

        vl.commitChanges()
        vl.updateExtents()

        self._layer = vl
        return True
