# -*- coding: utf-8 -*-
"""
/***************************************************************************
 GRMDockWidget
                                 A QGIS plugin
 GRM
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                             -------------------
        begin                : 2020-01-08
        git sha              : $Format:%H$
        copyright            : (C) 2020 by Hermesys
        email                : shpark@hermesys.co.kr
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 time
import webbrowser
from typing import Dict, Union

from qgis.core import QgsProject, QgsRasterLayer
from qgis.PyQt import QtGui, QtWidgets
from qgis.PyQt.QtCore import QFileInfo, pyqtSignal
from qgis.PyQt.QtWidgets import QFileDialog, QTreeWidgetItem

from grm.dialogs.Weather_data import ClimateDataDialog
from grm.dialogs.LandCover_dialog import LandCoverDialog
from grm.GRM_dialog import GRMDialog
from grm.lib.File_Class import ChFile_Exists
from grm.lib.Util import MsError, MsInfo, MsTitle
from grm.lib.xmltodict import parse, unparse
from grm.ui.GRM_dockwidget_base import Ui_GRMDockWidgetBase

# from .lib.File_Class import *
# from .lib.Util import *
# from .lib.xmltodict import *
from grm.Watershed_dialog import WatershedDialog
from grm.XMLCheck import xmls
from grm.XMLMake import make

path = os.path.dirname(os.path.realpath(__file__))
project_icon_path = path + "\image\Folder_3.png"
input_data_icon_path = path + "\image\database.png"
run_GRM_icon_path = path + "\image\settings.png"
GRMTools = path + "\image\Tool.png"
help_icon_path = path + "\image\information.png"
Analysis = path + "\image\Analysis.png"
Flask = path + "\image\Flask.png"

_XmlCheck = xmls()
_XmlCreat = make()
# 트리 위제 목록이 비활성화 중에도 클릭 이벤트가 처리 되는 현상으로
# 구분 하기위해서 넣음
_ProjectFlage = False


class GRMDockWidget(QtWidgets.QDockWidget, Ui_GRMDockWidgetBase):
    closingPlugin = pyqtSignal()

    def __init__(self, parent=None):
        super(GRMDockWidget, self).__init__(parent)
        self.setupUi(self)

        # 변수 초기화
        self._xmltodict: Union[Dict, None] = None

        # 화면 초기화
        self.initUI()

    def initUI(self):
        MsTitle("GRM")
        self.setWindowTitle("GRM")
        self.treeWidget.setItemsExpandable(True)
        self.treeWidget.setAnimated(True)
        self.treeWidget.setColumnCount(1)
        self.treeWidget.setHeaderHidden(True)

        # Project 메뉴 설정
        project_item = QTreeWidgetItem(self.treeWidget, ["Project"])
        project_item.setIcon(0, QtGui.QIcon(project_icon_path))
        QTreeWidgetItem(project_item, ["New Project"])
        QTreeWidgetItem(project_item, ["Open Project"])
        save_project_item = QTreeWidgetItem(project_item, ["Save Project"])
        save_project_item.setDisabled(True)
        save_as_project_item = QTreeWidgetItem(project_item, ["Save as Project"])
        save_as_project_item.setDisabled(True)

        # Input Data 메뉴 설정
        input_data_item = QTreeWidgetItem(self.treeWidget, ["Setup input data"])
        input_data_item.setIcon(0, QtGui.QIcon(input_data_icon_path))
        input_data_item.setDisabled(True)
        QTreeWidgetItem(input_data_item, ["Watershed"])
        QTreeWidgetItem(input_data_item, ["Land Cover / Soil"])
        QTreeWidgetItem(input_data_item, ["Weather Data"])

        # Setup / Run GRM 메뉴 설정
        setup_and_run_grm_item = QTreeWidgetItem(self.treeWidget, ["Setup / Run GRM"])
        setup_and_run_grm_item.setIcon(0, QtGui.QIcon(run_GRM_icon_path))
        setup_and_run_grm_item.setDisabled(True)

        # 도움말 메뉴 설정
        help_item = QTreeWidgetItem(self.treeWidget, ["Help"])
        QTreeWidgetItem(help_item, ["Download the GRM model manual"])
        QTreeWidgetItem(help_item, ["QGRM user's manual"])
        help_item.setIcon(0, QtGui.QIcon(help_icon_path))

        self.grmDialogFlag = False

        # 더블 클릭 했을대 메뉴 명칭 확인
        self.treeWidget.itemDoubleClicked.connect(self.OnDoubleClick)

    def OnDoubleClick(self, select_item: QTreeWidgetItem):
        try:
            # 프로젝트 파일 오픈
            item_text = select_item.text(0)
            is_enable = not select_item.isDisabled()

            if item_text == "New Project":
                self.NewProjectFile()

            elif item_text == "Open Project":
                self.OpenProjectFile()

            elif item_text == "Save Project" and is_enable:
                self.SaveProjectFile()

            elif item_text == "Save as Project" and is_enable:
                self.SaveASProjectFile()

            elif item_text == "Watershed" and is_enable:
                if self.grmDialogFlag == True:
                    self._grmDialogFlag = 1
                elif self.grmDialogFlag == False:
                    self._grmDialogFlag = 0
                Watershed = WatershedDialog(self._xmltodict, self._grmDialogFlag)
                Watershed.exec_()
                self._xmltodict = Watershed._xmltodict
                self._grmDialogFlag = Watershed._grmDialogFlag

            elif item_text == "Land Cover / Soil" and is_enable:
                if self.grmDialogFlag == True:
                    self._grmDialogFlag = 1
                if self.grmDialogFlag == False:
                    self._grmDialogFlag = 0
                LandCover = LandCoverDialog(
                    self._xmltodict,
                    self._LandCoverCount,
                    self._GreenAmptCount,
                    self._SoilDepthCount,
                    self._grmDialogFlag,
                )
                LandCover.exec_()
                self._xmltodict = LandCover._xmltodict
                self._LandCoverCount = LandCover._LandCoverCount
                self._GreenAmptCount = LandCover._GreenAmptCount
                self._SoilDepthCount = LandCover._SoilDepthCount
                self._grmDialogFlag = LandCover._grmDialogFlag

            elif item_text == "Weather Data" and is_enable:
                ClimateData = ClimateDataDialog(self._xmltodict)
                ClimateData.exec_()

            elif item_text == "Setup / Run GRM" and is_enable:
                try:
                    # 2022.01.05 동 : flag를 사용하지 않으면 GRMDialog 창이 클릭한 개수만큼 뜨게 됨.
                    # 창이 여러개 뜨면 grid line, flow direction을 캔버스에 표시할때 오류가 발생해서 1개의 창만 킬 수 있도록 변경
                    # 그 외, 개발할때 reload plugin 하기 전에 dialog 창이 켜진 상태로 reload를 진행하면 기존 레이어가 지워지지 않아서 오류가 발생할 수 있음.
                    def closeSignal():
                        self.grmDialogFlag = False

                    if not self.grmDialogFlag:
                        GRM = GRMDialog(
                            self._ProjectFile,
                            self._xmltodict,
                            self._WatchPointCount,
                            self._SubWatershedCount,
                            self._GreenAmptCount,
                            self._SoilDepthCount,
                            self._LandCoverCount,
                            self._FlowControlCount,
                            self._ChannelSettingsCount,
                        )

                        GRM.closeDialogEvent.connect(closeSignal)
                        GRM.show()
                        self.grmDialogFlag = True

                        self._xmltodict = GRM._xmltodict
                except AttributeError:
                    MsError("All input data is not set.")

            elif item_text == "QGRM user's manual":
                docs_url = "https://docs.google.com/document/d/15vySQ7c6e2fnKsJtovMoA7n9PoY7gnfdoUKRowD_vYY/edit"
                webbrowser.open_new(docs_url)

            elif item_text == "Download the GRM model manual":
                docs_url = "https://github.com/floodmodel/GRM/tree/master/DownloadStableVersion"
                webbrowser.open_new(docs_url)

        except Exception as e:
            self.grmDialogFlag = False
            MsError(e)

    def NewProjectFile(self):
        self._SubWatershedCount = 0
        self._WatchPointCount = 0
        self._FlowControlCount = 0
        self._GreenAmptCount = 0
        self._SoilDepthCount = 0
        self._LandCoverCount = 0
        self._RainFallCount = 0

        # 2020-04-21 박: 추가 항목
        self._ChannelSettingsCount = 0

        # New Project 시에 GMP 파일 새로 생성
        filename = QFileDialog.getSaveFileName(self, "New project", "", "*.gmp")[0]

        if filename:
            self._ProjectFile = filename
            _XmlCreat.Make_GMP_File(filename)
            if len(filename) > 0:
                self.set_enable()
            Projectfile = open(filename, "r")
            data = Projectfile.read()
            Projectfile.close()
            time.sleep(1)
            if ChFile_Exists(filename):
                MsInfo("[" + str(self._ProjectFile) + "]" + " GMP file created. ")
            else:
                MsError("The GMP file creation failed.")
            self._xmltodict = dict(parse(data))
        else:
            return

    def OpenProjectFile(self):
        # 프로젝트 파일 찾을 다이얼 로그
        try:
            # 프로젝트 파일 불러오기
            self.filename = QFileDialog.getOpenFileName(
                self,
                "Open project",
                "",
                "GRM Project xml files (*.gmp)",
                options=QFileDialog.DontUseNativeDialog,
            )[0]
            if ChFile_Exists(self.filename):
                self._ProjectFile = self.filename

                # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함

                _XmlCheck.Check_Gmp_xml(self._ProjectFile)
                time.sleep(1)
                self._LandCoverCount = _XmlCheck._LandCoverCount
                self._GreenAmptCount = _XmlCheck._GreenAmptCount
                self._SoilDepthCount = _XmlCheck._SoilDepthCount
                self._WatchPointCount = _XmlCheck._WatchPointCount
                self._SubWatershedCount = _XmlCheck._SubWatershedCount
                self._FlowControlCount = _XmlCheck._FlowControlCount
                self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount

                # 프로젝트 파일 확인 후에 QtreeWidget 재설정(비활성화 메뉴 활성화)
                if len(self.filename) > 0:
                    self.set_enable()

                # 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴
                Projectfile = open(self.filename, "r")
                data = Projectfile.read()
                Projectfile.close()

                # 읽어온 파일 내용(XML)을 dictionary 로 변경
                self._xmltodict = dict(parse(data))

                # dictionary 값을 받아서 레이어 목록을 Qgis 에 올림
                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["DomainFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"]["DomainFile"]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["SlopeFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"]["SlopeFile"]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"][
                        "FlowDirectionFile"
                    ]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"][
                            "FlowDirectionFile"
                        ]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["FlowAccumFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"][
                            "FlowAccumFile"
                        ]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["StreamFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"]["StreamFile"]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["LandCoverFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"][
                            "LandCoverFile"
                        ]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["SoilDepthFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"][
                            "SoilDepthFile"
                        ]
                    )

                if (
                    self._xmltodict["GRMProject"]["ProjectSettings"]["SoilTextureFile"]
                    is not None
                ):
                    self.AddlayerQGIS(
                        self._xmltodict["GRMProject"]["ProjectSettings"][
                            "SoilTextureFile"
                        ]
                    )

                # 현재 열은 프로젝트 파일 경로와 GMP 내부 프로젝트 파일 경로 동기화
        except Exception as wa:
            MsError(wa)

    def SaveProjectFile(self):
        DictoXml = unparse(self._xmltodict)
        fw = open(self._ProjectFile, "w+")
        fw.write(DictoXml)
        fw.close()

        # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함
        _XmlCheck.Check_Gmp_xml(self._ProjectFile)
        time.sleep(1)
        self._LandCoverCount = _XmlCheck._LandCoverCount
        self._GreenAmptCount = _XmlCheck._GreenAmptCount
        self._SoilDepthCount = _XmlCheck._SoilDepthCount
        self._WatchPointCount = _XmlCheck._WatchPointCount
        self._SubWatershedCount = _XmlCheck._SubWatershedCount
        self._FlowControlCount = _XmlCheck._FlowControlCount
        self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount

        ## 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴
        Projectfile = open(self._ProjectFile, "r")
        data = Projectfile.read()
        Projectfile.close()

        # 읽어온 파일 내용(XML)을 dictionary 로 변경
        self._xmltodict = dict(parse(data))
        MsInfo("[" + self._ProjectFile + "] " + "was saved. ")

    def SaveASProjectFile(self):
        SaveAsPath = QFileDialog.getSaveFileName(self, "Save as project", "", "*.gmp")[
            0
        ]
        if SaveAsPath == "":
            MsInfo("[" + str(self._ProjectFile) + "]" + " Save was cancelled. ")
            return
        else:
            self._ProjectFile = SaveAsPath
            DictoXml = unparse(self._xmltodict)
            fw = open(self._ProjectFile, "w+")
            fw.write(DictoXml)
            fw.close()
            #             self.indent(self._ProjectFile)
            time.sleep(1)
            # 2020-02-10 박: XML 체크할때 Landcover 데이터를 배열에 받아서 반환 함
            _XmlCheck.Check_Gmp_xml(self._ProjectFile)

            self._LandCoverCount = _XmlCheck._LandCoverCount
            self._GreenAmptCount = _XmlCheck._GreenAmptCount
            self._SoilDepthCount = _XmlCheck._SoilDepthCount
            self._WatchPointCount = _XmlCheck._WatchPointCount
            self._SubWatershedCount = _XmlCheck._SubWatershedCount
            self._GreenAmptCount = _XmlCheck._GreenAmptCount
            self._SoilDepthCount = _XmlCheck._SoilDepthCount
            self._LandCoverCount = _XmlCheck._LandCoverCount
            self._FlowControlCount = _XmlCheck._FlowControlCount
            self._ChannelSettingsCount = _XmlCheck._ChannelSettingsCount

            ## 2017/09/17 프로젝트 파일(XML)을 그냥 일반 문서 처럼 읽어옴
            Projectfile = open(self._ProjectFile, "r")
            data = Projectfile.read()
            Projectfile.close()
            # 읽어온 파일 내용(XML)을 dictionary 로 변경
            self._xmltodict = dict(parse(data))

            MsInfo("[" + self._ProjectFile + "]" + " was saved. ")

    # gis에 올리기
    def AddlayerQGIS(self, path):
        if (os.path.isfile(path)) and (self.CheckLayer(path)):
            fileInfo = QFileInfo(path)
            baseName = fileInfo.baseName()
            layer = QgsRasterLayer(path, baseName, "gdal")
            QgsProject.instance().addMapLayer(layer)

    # 레이어가 Qgis에 올라와 있는지 확인 (현재 QGIS에 올라온 레이어면 올리지 않음)
    def CheckLayer(self, layerpath):
        for lyr in QgsProject.instance().mapLayers().values():
            if lyr.dataProvider().dataSourceUri().upper() == layerpath.upper():
                return False
        return True

    # tree widget 초기화 시키고 다시 메뉴 셋팅(프로젝트 파일 로드후 비활성화 메뉴 활성화로 변경)
    def set_enable(self):
        self.__set_enable_widget(self.treeWidget.invisibleRootItem())

    def __set_enable_widget(self, item: QTreeWidgetItem):
        item.setDisabled(False)
        for i in range(item.childCount()):
            self.__set_enable_widget(item.child(i))


if __name__ == "__main__":
    import os

    os.environ[
        "QT_QPA_PLATFORM_PLUGIN_PATH"
    ] = r"C:\Program Files\QGIS 3.10\apps\Qt5\plugins"

    import sys

    from qgis.PyQt.QtWidgets import QApplication

    from grm.lib.Util import MsTitle

    MsTitle("GRM Dock Widget")

    app = QApplication(sys.argv)
    w = GRMDockWidget()
    w.show()
    sys.exit(app.exec_())
