# -*- coding: utf-8 -*-
"""
/***************************************************************************
 LfbRegenerationWildlifeImpactDialog
                                 A QGIS plugin
 Lfb Regeneration and Wildlife Impact Monitoring
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2023-05-08
        git sha              : $Format:%H$
        copyright            : (C) 2023 by Grünecho
        email                : support@grunecho.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
import copy
import json

from qgis.core import QgsMessageLog, QgsProject, QgsVectorLayer, QgsJsonUtils, QgsField, QgsFields, QgsVectorFileWriter, QgsCoordinateTransformContext
from qgis.PyQt import QtWidgets, uic
from qgis.PyQt.QtCore import QCoreApplication, QSettings, QTranslator
from qgis.PyQt.QtWidgets import QDialog, QTableWidgetItem, QPushButton

from PyQt5.QtGui import QCursor

from PyQt5.uic import loadUi
from PyQt5 import QtCore

from jsonschema import Draft7Validator, exceptions

from ...utils.helper import Utils


UI_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'array_field.ui'))


class ArrayField(QtWidgets.QWidget, UI_CLASS):
    inputChanged = QtCore.pyqtSignal(object)
    rowSelected = QtCore.pyqtSignal(object)

    def __init__(self, interface, json, schema, key, schemaErrors):
        """Constructor."""

        from .views.arrayView import ArrayView

        QDialog.__init__(self, interface.mainWindow())

        self.setupUi(self)

        if(key not in json):
            json[key] = None

        
        self.selectedRow = None
        self.json = json
        self.schema = schema
        self.key = key
        self.draftFormErrors = schemaErrors

        self.headerSet = False
        
        self.defaultValue = {} #copy.deepcopy(self.json[self.key][0])
        #del self.json[self.key][0]

        self.lfbArrayGroup.setTitle(self.schema['title'])
        
        self.child = ArrayView(interface, self.defaultValue , schema['items'], key, schemaErrors)
        self.child.inputChanged.connect(self.setInputText)
        self.lfbArrayInput.addWidget(self.child)

        self.lfbAddBtn.clicked.connect(self.addRow)
        self.lfbAddBtn.setEnabled(False)

        self.tableHeaders = []
        for attr, value in self.schema['items']['properties'].items():
            self.tableHeaders.append(value['title'])

        self.tableHeaders.append('bearbeiten')
        self.tableHeaders.append('löschen')

        self.show()

        self.buttonStyle = " QgsCollapsibleGroupBoxBasic::title, QgsCollapsibleGroupBox::title {left: 10px; top: -10px; padding-left: 10px; border: 2px solid gray; border-radius:10px; font-size: 8px; background: #cdcdcd; padding: 3px;} "
        self.widgetStyle = " QgsCollapsibleGroupBoxBasic { background: rgba(0,0,0,0.05); margin: 10px; border: 2px solid green; padding: 10px; border-radius:10px;} "
        self.widgetErrorStyle = " QgsCollapsibleGroupBoxBasic { background: rgba(0,0,0,0.05); margin: 10px; border: 2px solid red; padding: 10px; border-radius:10px;} "

        self.lfbArrayFormGroup.setStyleSheet(self.buttonStyle + self.widgetStyle)
        self.lfbArrayFormGroup.setTitle('NEUE ZEILE HINZUFÜGEN')
        # .setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        
        #errors = self.validate()
        #for error in errors:
        #    self.draftFormErrors.append(error)

        self.lfb_array_error_2.hide()

        self.show()

    def update_errors(self, message):
        

        #self.lfb_array_error_msg.hide()

        for error in self.draftFormErrors:
            if self.key in error.relative_schema_path:
                self.lfb_array_error_msg.setText(error.message)
                self.lfb_array_error_msg.show()
                break

    def setTableHeaders(self, headers, data):

        self.lfbArrayOutput.setColumnCount(len(headers))
        self.lfbArrayOutput.setRowCount(len(data))

        self.lfbArrayOutput.setHorizontalHeaderLabels(headers)
        #self.lfbArrayOutput.horizontalHeader().setStretchLastSection(True)
        #self.lfbArrayOutput.horizontalHeader().setStretchFirstSection(True)
        for i in range(0, len(headers)):
            self.lfbArrayOutput.horizontalHeader().setSectionResizeMode(i, QtWidgets.QHeaderView.ResizeToContents)

        self.lfbArrayOutput.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
        #self.lfbArrayOutput.horizontalHeader().setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)

    def setTableData(self, data):
        self.lfbArrayOutput.clear()

        self.setTableHeaders(self.tableHeaders, data)

        for row in range(0, len(data)):
            idx = 0
            for attr, column in self.schema['items']['properties'].items():
                if attr in data[row]:
                    output = str(data[row][attr])
                else:
                    output = ''

                self.lfbArrayOutput.setItem(row, idx, QTableWidgetItem(str(output)))
                idx += 1

            # create an cell widget
            btn = QPushButton(self.lfbArrayOutput)
            btn.clicked.connect(self.make_editRow(row))
            btn.setStyleSheet("color: green;")
            btn.setText('bearbeiten')
            btn.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
            self.lfbArrayOutput.setCellWidget(row, idx, btn)
            idx += 1

            # create an cell widget
            btn = QPushButton(self.lfbArrayOutput)
            btn.clicked.connect(self.make_removeRow(row))
            btn.setStyleSheet("color: red;")
            btn.setText('löschen')
            btn.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
            self.lfbArrayOutput.setCellWidget(row, idx, btn)
            idx += 1

            

    def make_editRow(self, row):
        def editRow():
            self.editRow(row)
        return editRow
    
    def editRow(self, row):

        self.selectedRow = row
        
        # Mark the row as selected
        self.lfbArrayOutput.selectRow(row)

        # Open the form
        self.lfbArrayFormGroup.setCollapsed(False)

        # Create Copy of the row values
        self.defaultValue = copy.deepcopy(self.json[self.key][row])
        
        # Delete the row from the json
        self.child.setJson(self.defaultValue, True, row)
        

        self.lfbAddBtn.setText('ÜBERSCHREIBEN')
        
       
    
    def make_removeRow(self, row):
        def removeRow():
            self.removeRow(row)
        return removeRow
        
        #self.lfbArrayOutput.removeRow(row)

    def removeRow(self, row):
        res = Utils.confirmDialog(self, 'Zeile löschen', 'Möchtest du die Zeile wirklich löschen?')
        if res == QtWidgets.QMessageBox.Yes:
            del self.json[self.key][row]
            self.setTableData(self.json[self.key])
            self.inputChanged.emit(self.json)

    def addRow(self):
        #self.validate()
        newValue = copy.deepcopy(self.defaultValue)
        
        if self.selectedRow is not None and self.selectedRow >= 0 and self.selectedRow < len(self.json[self.key]):
            self.json[self.key][self.selectedRow] = newValue
        else:
            self.json[self.key].insert(0, newValue)
 

        self.inputChanged.emit(self.json)
        self.setTableData(self.json[self.key])
        self.resetForm()

    def resetForm(self):
        self.defaultValue = {}
        self.child.setJson(self.defaultValue, True)
        self.lfbArrayFormGroup.setCollapsed(True)
        
        self.selectedRow = None
        self.lfbAddBtn.setText('HINZUFÜGEN')

    def setJson(self, newJson, setFields = True):
        self.json = newJson
        self.setTableData(self.json[self.key])

    def setInputText(self, value, row = None):
        self.draftFormErrors.clear()

        errors = self.validate(False)
        for error in errors:
            if row is None:
                self.draftFormErrors.append(error)
        
        self.child.triggerErrors(self.draftFormErrors)

    def validate(self, emit = True):
        return

        # https://python-jsonschema.readthedocs.io/en/stable/validate/
        v = Draft7Validator(self.schema)
        errors = sorted(v.iter_errors([self.defaultValue]), key=lambda e: e.path)

        
        default_value_0 = self.defaultValue

        self.lfb_array_error_2.hide()
        if self.selectedRow is None and 'distanz' in default_value_0 and 'azimut' in default_value_0:
            if default_value_0['distanz'] is not None and default_value_0['azimut'] is not None:
                self.lfb_array_error_2.hide()
                for element in self.json[self.key]:
                    if element['distanz'] == default_value_0['distanz'] and element['azimut'] == default_value_0['azimut']:
                        errors.append(exceptions.ValidationError(
                            message='Es existiert bereits ein Eintrag mit dieser Entfernung und diesem Azimut.',
                            validator='minItems',
                            schema_path=['allOf', 3, 'then', 'properties', 't_bestockung', 'properties', 't_bestockung', 'minItems']
                        ))
                        self.lfb_array_error_2.show()
                        self.lfb_array_error_label.setText('Es existiert bereits ein Eintrag mit dieser Entfernung und diesem Azimut.')

        if len(errors) == 0:
            self.lfbAddBtn.setEnabled(True)
            self.lfbArrayFormGroup.setStyleSheet(self.buttonStyle + self.widgetStyle)
        else:
            self.lfbAddBtn.setEnabled(False)
            self.lfbArrayFormGroup.setStyleSheet(self.buttonStyle + self.widgetErrorStyle)

        if emit:
            self.inputChanged.emit(self.json)

        return errors
