# /**********************************************************************
# *                                                                     *
# * Copyright (c) 2021 Javier Braña <javier.branagutierrez@gmail.com>  *
# *                                                                     *
# * This program is free software; you can redistribute it and/or modify*
# * it under the terms of the GNU Lesser General Public License (LGPL)  *
# * as published by the Free Software Foundation; either version 2 of   *
# * the License, or (at your option) any later version.                 *
# * for detail see the LICENCE text file.                               *
# *                                                                     *
# * This program is distributed in the hope that it will be useful,     *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of      *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
# * GNU Library General Public License for more details.                *
# *                                                                     *
# * You should have received a copy of the GNU Library General Public   *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307*
# * USA                                                                 *
# *                                                                     *
# ***********************************************************************

import FreeCAD
import utm

if FreeCAD.GuiUp:
    import FreeCADGui
    from PySide import QtCore, QtGui
    from PySide.QtCore import QT_TRANSLATE_NOOP
    from PySide2.QtWebEngineWidgets import QWebEngineView
    from PySide2.QtWebChannel import QWebChannel
    import os
else:
    # \cond
    def translate(ctxt,txt):
        return txt
    def QT_TRANSLATE_NOOP(ctxt,txt):
        return txt
    # \endcond

import PVPlantResources
from PVPlantResources import DirIcons as DirIcons
from PVPlantResources import DirResources as DirResources


class MapWindow(QtGui.QWidget):
    def __init__(self, WinTitle="MapWindow"):
        super(MapWindow, self).__init__()
        self.raise_()
        self.lat = 0
        self.lon = 0
        self.WinTitle = WinTitle

        self.setupUi()

    def setupUi(self):
        self.ui = FreeCADGui.PySideUic.loadUi(PVPlantResources.__dir__ + "/PVPlantGeoreferencing.ui", self)

        self.resize(1200, 800)
        self.setWindowTitle(self.WinTitle)
        self.setWindowIcon(QtGui.QIcon(os.path.join(DirIcons, "Location.svg")))
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)

        self.layout = QtGui.QHBoxLayout(self)
        self.layout.setContentsMargins(4, 4, 4, 4)

        LeftWidget = QtGui.QWidget(self)
        LeftLayout = QtGui.QVBoxLayout(LeftWidget)
        LeftWidget.setLayout(LeftLayout)
        LeftLayout.setContentsMargins(0, 0, 0, 0)

        RightWidget = QtGui.QWidget(self)
        RightWidget.setFixedWidth(350)
        RightLayout = QtGui.QVBoxLayout(RightWidget)
        RightWidget.setLayout(RightLayout)
        RightLayout.setContentsMargins(0, 0, 0, 0)

        self.layout.addWidget(LeftWidget)
        self.layout.addWidget(RightWidget)

        # Left Widgets:
        # -- Search Bar:
        self.valueSearch = QtGui.QLineEdit(self)
        self.valueSearch.setPlaceholderText("Search")
        self.valueSearch.returnPressed.connect(self.onSearch)

        searchbutton = QtGui.QPushButton('Search')
        searchbutton.setFixedWidth(80)
        searchbutton.clicked.connect(self.onSearch)

        SearchBarLayout = QtGui.QHBoxLayout(self)
        SearchBarLayout.addWidget(self.valueSearch)
        SearchBarLayout.addWidget(searchbutton)
        LeftLayout.addLayout(SearchBarLayout)

        # -- Webbroser:
        self.view = QWebEngineView()
        self.channel = QWebChannel(self.view.page())
        self.view.page().setWebChannel(self.channel)
        self.channel.registerObject("MyApp", self)
        file = os.path.join(DirResources, "webs", "main.html")
        self.view.page().loadFinished.connect(self.onLoadFinished)
        self.view.page().load(QtCore.QUrl.fromLocalFile(file))
        LeftLayout.addWidget(self.view)
        # self.layout.addWidget(self.view, 1, 0, 1, 3)

        # -- Latitud y longitud:
        self.labelCoordinates = QtGui.QLabel()
        self.labelCoordinates.setFixedHeight(21)
        LeftLayout.addWidget(self.labelCoordinates)
        # self.layout.addWidget(self.labelCoordinates, 2, 0, 1, 3)

        # Right Widgets:
        labelKMZ = QtGui.QLabel()
        labelKMZ.setText("Cargar un archivo KMZ/KML:")
        self.kmlButton = QtGui.QPushButton()
        self.kmlButton.setFixedSize(32, 32)
        self.kmlButton.setIcon(QtGui.QIcon(os.path.join(DirIcons, "googleearth.svg")))
        widget = QtGui.QWidget(self)
        layout = QtGui.QHBoxLayout(widget)
        widget.setLayout(layout)
        layout.addWidget(labelKMZ)
        layout.addWidget(self.kmlButton)
        RightLayout.addWidget(widget)

        # -----------------------
        self.groupbox = QtGui.QGroupBox("Importar datos desde:")
        self.groupbox.setCheckable(True)
        self.groupbox.setChecked(True)
        radio1 = QtGui.QRadioButton("Google Elevation")
        radio2 = QtGui.QRadioButton("Nube de Puntos")
        radio3 = QtGui.QRadioButton("Datos GPS")
        radio1.setChecked(True)

        # buttonDialog = QtGui.QPushButton('...')
        # buttonDialog.setEnabled(False)

        vbox = QtGui.QVBoxLayout(self)
        vbox.addWidget(radio1)
        vbox.addWidget(radio2)
        vbox.addWidget(radio3)

        self.groupbox.setLayout(vbox)
        RightLayout.addWidget(self.groupbox)
        # ------------------------

        verticalSpacer = QtGui.QSpacerItem(20, 48, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        RightLayout.addItem(verticalSpacer)

        self.bAccept = QtGui.QPushButton('Accept')
        self.bAccept.clicked.connect(self.onAcceptClick)
        RightLayout.addWidget(self.bAccept)

        # signals/slots
        QtCore.QObject.connect(self.kmlButton, QtCore.SIGNAL("clicked()"), self.importKML)


    def onLoadFinished(self):
        file = os.path.join(DirResources, "webs", "map.js")
        frame = self.view.page()
        with open(file, 'r') as f:
            frame.runJavaScript(f.read())

    def onSearch(self):
        if self.valueSearch.text() == "":
            return

        from geopy.geocoders import Nominatim

        geolocator = Nominatim(user_agent="http")
        location = geolocator.geocode(self.valueSearch.text())
        print(location.raw)
        self.valueSearch.setText(location.address)
        self.panMap(location.longitude, location.latitude, location.raw['boundingbox'])

    def onAcceptClick(self):
        frame = self.view.page()
        # 1. georeferenciar
        frame.runJavaScript(
            "MyApp.georeference(drawnItems.getBounds().getCenter().lat, drawnItems.getBounds().getCenter().lng);"
        )

        # 2. importar todos los elementos dibujados:
        frame.runJavaScript(
            "var data = drawnItems.toGeoJSON();"
            "MyApp.shapes(JSON.stringify(data));"
        )
        self.close()

    @QtCore.Slot(float, float)
    def onMapMove(self, lat, lng):
        self.lat = lat
        self.lon = lng
        x, y, zone_number, zone_letter = utm.from_latlon(lat, lng)
        self.labelCoordinates.setText('Longitud: {:.5f}, Latitud: {:.5f}'.format(lng, lat) +
                                      '  |  UTM: ' + str(zone_number) + zone_letter +
                                      ', {:.5f}m E, {:.5f}m N'.format(x, y))

    @QtCore.Slot(float, float)
    def georeference(self, lat, lng):
        import PVPlantSite
        from geopy.geocoders import Nominatim
        Site = PVPlantSite.get(create=True)
        Site.Proxy.setLatLon(lat, lng)

        geolocator = Nominatim(user_agent="http")
        location = geolocator.reverse('{:.5f}, {:.5f}'.format(lat, lng))
        if location:
            if location.raw["address"].get("road"):
                str = location.raw["address"]["road"]
                if location.raw["address"].get("house_number"):
                    str += ' ({0})'.format(location.raw["address"]["house_number"])
                Site.Address = str
            if location.raw["address"].get("city"):
                Site.City = location.raw["address"]["city"]
            if location.raw["address"].get("postcode"):
                Site.PostalCode = location.raw["address"]["postcode"]
            if location.raw["address"].get("address"):
                Site.Region = '{0}'.format(location.raw["address"]["province"])
            if location.raw["address"].get("state"):
                if Site.Region != "":
                    Site.Region += " - "
                Site.Region += '{0}'.format(location.raw["address"]["state"])   # province - state
            Site.Country = location.raw["address"]["country"]

    @QtCore.Slot(str)
    def shapes(self, drawnItems):
        import geojson
        import PVPlantImportGrid as ImportElevation
        import Draft

        items = geojson.loads(drawnItems)
        for item in items['features']:
            if item['geometry']['type'] == "Point":     # 1. if the feature is a Point or Circle:
                coord = item['geometry']['coordinates']
                point = ImportElevation.getElevationFromOE([[coord[0], coord[1]],])
                c = FreeCAD.Vector(point[0][0], point[0][1], point[0][2])
                if item['properties'].get('radius'):
                    r = round(item['properties']['radius'] * 1000, 0)
                    p = FreeCAD.Placement()
                    p.Base = c
                    obj = Draft.makeCircle(r, placement=p, face=False)
                else:
                    ''' do something '''
                    obj = Draft.make_point(c * 1000, color=(0.5, 0.3, 0.6), point_size=10)
            else:                                       # 2. if the feature is a Polygon or Line:
                cw = False
                name = "Línea"
                lp = item['geometry']['coordinates']
                if item['geometry']['type'] == "Polygon":
                    cw = True
                    name = "Area"
                    lp = item['geometry']['coordinates'][0]

                pts = []
                for cords in lp:
                    pts.append([cords[1], cords[0]])
                tmp = ImportElevation.getElevationFromOE(pts)
                pts = []
                for p in tmp:
                    pts.append(p.sub(FreeCAD.ActiveDocument.Site.Origin))

                obj = Draft.makeWire(pts, closed=cw, face=False)
                obj.Placement.Base = FreeCAD.ActiveDocument.Site.Origin
                obj.Label = name
                Draft.autogroup(obj)

            if item['properties'].get('name'):
                obj.Label = item['properties']['name']

        FreeCAD.activeDocument().recompute()
        FreeCADGui.updateGui()
        FreeCADGui.SendMsgToActiveView("ViewFit")

    def panMap(self, lng, lat, geometry=""):
        frame = self.view.page()
        bbox = "[{0}, {1}], [{2}, {3}]".format(float(geometry[0]), float(geometry[2]),
                                               float(geometry[1]), float(geometry[3]))
        command =  'map.panTo(L.latLng({lt}, {lg}));'.format(lt=lat, lg=lng)
        command += 'map.fitBounds([{box}]);'.format(box=bbox)
        frame.runJavaScript(command)

    def importKML(self):
        file = QtGui.QFileDialog.getOpenFileName(None, "FileDialog", "", "Google Earth (*.kml *.kmz)")[0]

        from lib.kml2geojson import kmz_convert
        layers = kmz_convert(file, "", )
        frame = self.view.page()
        for layer in layers:
            command = "drawnItems.addLayer(L.geoJSON({0}));".format(layer)
            frame.runJavaScript(command)


class _CommandPVPlantGeoreferencing:

    def GetResources(self):
        return {'Pixmap': str(os.path.join(DirIcons, "Location.svg")),
                'Accel': "G, R",
                'MenuText': QT_TRANSLATE_NOOP("Georeferencing","Georeferencing"),
                'ToolTip': QT_TRANSLATE_NOOP("Georeferencing","Referenciar el lugar")}

    def Activated(self):
        self.form = MapWindow()
        self.form.show()

    def IsActive(self):
        if FreeCAD.ActiveDocument:
            return True
        else:
            return False

if FreeCAD.GuiUp:
    FreeCADGui.addCommand('PVPlantGeoreferencing',_CommandPVPlantGeoreferencing())

