# -*- coding: utf-8 -*-
"""
functions to use GEE within Qgis python script
"""
import math
import ee

from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsPointXY, QgsRectangle
from qgis.utils import iface
from qgis.PyQt.QtCore import QEventLoop, QTimer


def addLayer(eeObject, visParams=None, name=None, shown=True, opacity=1.0):
    """
        Adds a given EE object to the map as a layer.

        https://developers.google.com/earth-engine/api_docs#mapaddlayer

        Uses:
            >>> from ee_plugin import Map
            >>> Map.addLayer(.....)
    """
    from ee_plugin.utils import add_or_update_ee_layer

    add_or_update_ee_layer(eeObject, visParams, name, shown, opacity)


def centerObject(feature, zoom=None):
    """
        Centers the map view on a given object.

        https://developers.google.com/earth-engine/api_docs#mapcenterobject

        Uses:
            >>> from ee_plugin import Map
            >>> Map.centerObject(feature)
    """

    if not hasattr(feature, 'geometry'):
        feature = ee.Feature(feature)

    if not zoom:
        # make sure our geometry is in geo
        rect = feature.geometry().transform(ee.Projection('EPSG:4326'), 1)

        # get coordinates
        coords = rect.bounds().getInfo()['coordinates'][0]
        xmin = coords[0][0]
        ymin = coords[0][1]
        xmax = coords[2][0]
        ymax = coords[2][1]

        # construct QGIS geometry
        rect = QgsRectangle(xmin, ymin, xmax, ymax)

        # transform rect to a crs used by current project
        crs_src = QgsCoordinateReferenceSystem('EPSG:4326')
        crs_dst = QgsCoordinateReferenceSystem(QgsProject.instance().crs())
        geo2proj = QgsCoordinateTransform(crs_src, crs_dst, QgsProject.instance())
        rect_proj = geo2proj.transform(rect)

        # center geometry
        iface.mapCanvas().zoomToFeatureExtent(rect_proj)
    else:
        # set map center to feature centroid at a specified zoom
        center = feature.geometry().centroid().coordinates().getInfo()
        setCenter(center[0], center[1], zoom)


def getBounds(asGeoJSON=False):
    """
        Returns the bounds of the current map view, as a list in the format [west, south, east, north] in degrees.

        https://developers.google.com/earth-engine/api_docs#mapgetbounds

        Uses:
            >>> from ee_plugin import Map
            >>> bounds = Map.getBounds(True)
            >>> Map.addLayer(bounds, {}, 'bounds')
    """
    ex = iface.mapCanvas().extent()
    # return ex
    xmax = ex.xMaximum()
    ymax = ex.yMaximum()
    xmin = ex.xMinimum()
    ymin = ex.yMinimum()

    # return as [west, south, east, north]
    if not asGeoJSON:
        return [xmin, ymin, xmax, ymax]

    # return as geometry
    crs = iface.mapCanvas().mapSettings().destinationCrs().authid()

    return ee.Geometry.Rectangle([xmin, ymin, xmax, ymax], crs, False)


def getCenter():
    """
        Returns the coordinates at the center of the map.

        https://developers.google.com/earth-engine/api_docs#mapgetcenter

        Uses:
            >>> from ee_plugin import Map
            >>> center = Map.getCenter()
            >>> Map.addLayer(center, { 'color': 'red' }, 'center')
    """
    center = iface.mapCanvas().center()

    crs = iface.mapCanvas().mapSettings().destinationCrs().authid()

    return ee.Geometry.Point([center.x(), center.y()], crs)


def setCenter(lon, lat, zoom=None):
    """
        Centers the map view at the given coordinates with the given zoom level. If no zoom level is provided, it uses the most recent zoom level on the map.

        https://developers.google.com/earth-engine/api_docs#mapsetcenter

        Uses:
            >>> from ee_plugin import Map
            >>> Map.setCenter(lon, lat, zoom)
    """
    # wait 100 milliseconds while load the ee image
    loop = QEventLoop()
    QTimer.singleShot(100, loop.quit)
    loop.exec_()
    ### center
    center_point_in = QgsPointXY(lon, lat)
    # convert coordinates
    crsSrc = QgsCoordinateReferenceSystem('EPSG:4326')
    crsDest = QgsCoordinateReferenceSystem(QgsProject.instance().crs())
    xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance())
    # forward transformation: src -> dest
    center_point = xform.transform(center_point_in)
    iface.mapCanvas().setCenter(center_point)

    ### zoom
    if zoom is not None:
        # transform the zoom level to scale
        scale_value = 591657550.5 / 2 ** (zoom - 1)
        iface.mapCanvas().zoomScale(scale_value)


def getScale():
    """
        Returns the approximate pixel scale of the current map view, in meters.

        https://developers.google.com/earth-engine/api_docs#mapgetscale

        Uses:
            >>> from ee_plugin import Map
            >>> print(Map.getScale())
    """

    return iface.mapCanvas().scale() / 1000


def getZoom():
    """
        Returns the current zoom level of the map.

        https://developers.google.com/earth-engine/api_docs#mapgetzoom

        Note that in QGIS zoom is a floating point number

        Uses:
            >>> from ee_plugin import Map
            >>> print(Map.getZoom())
    """

    # from https://gis.stackexchange.com/questions/268890/get-current-zoom-level-from-qgis-map-canvas
    scale = iface.mapCanvas().scale()
    dpi = iface.mainWindow().physicalDpiX()
    maxScalePerPixel = 156543.04
    inchesPerMeter = 39.37
    zoom = math.log((dpi * inchesPerMeter * maxScalePerPixel / scale), 2)

    return zoom


def setZoom(zoom):
    """
        Sets the zoom level of the map.

        https://developers.google.com/earth-engine/api_docs#mapsetzoom

        Uses:
            >>> from ee_plugin import Map
            >>> Map.setZoom(15)
    """

    center = getCenter()
    centerObject(ee.Feature(center), zoom)
