# -*- coding: utf-8 -*-
"""
/***************************************************************************
 go2mapillaryDockWidget
                                 A QGIS plugin
 mapillary filter
                             -------------------
        begin                : 2016-01-21
        git sha              : $Format:%H$
        copyright            : (C) 2016 by enrico ferreguti
        email                : enricofer@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 sys
import datetime

from PyQt5 import QtWidgets, uic
from PyQt5.QtCore import pyqtSignal, QDate, QDateTime, QPoint


from qgis.core import QgsPointXY, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, Qgis
from qgis.gui import QgsMapTool

from .mapillary_api import mapillaryApi

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'mapillary_filter_dialog_base.ui'))


class mapillaryFilter(QtWidgets.QDialog, FORM_CLASS):

    closingPlugin = pyqtSignal()

    def __init__(self,module, parent=None):
        """Constructor."""
        super(mapillaryFilter, self).__init__(parent)
        # Set up the user interface from Designer.
        # After setupUI you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)
        self.module = module
        self.iface = module.iface
        self.setWindowTitle("go2mapillary filter")
        self.fromDateWidget.setDate(QDate(2014, 1, 1))
        self.toDateWidget.setDate(QDate.currentDate())
        self.buttonBox.accepted.connect(self.setFilter)
        self.addUserFilter.clicked.connect(self.addUserAction)
        self.removeUserFilter.clicked.connect(self.removeUserAction)
        self.sampleButton.clicked.connect(self.sampleOnCanvasAction)
        self.level = None
        self.mapillaryApi = mapillaryApi()
        self.setFilter()


    def setFilter(self):
        users_list = []
        userkeys_list = []
        for row in range(0,self.userFiltersTable.rowCount()):
            users_list.append(self.userFiltersTable.item(row,0).text())
            userkeys_list.append("'%s'" % self.userFiltersTable.item(row,1).text())

        self.filter = {
            'byDate':{
                'enabled': self.date_group.isChecked(),
                'from':  self.fromDateWidget.dateTime().toTime_t()*1000, #QDateTime(self.fromDateWidget.date()).toTime_t()*1000,
                'to': self.toDateWidget.dateTime().toTime_t()*1000 #QDateTime(self.toDateWidget.date()).toTime_t()*1000
            },
            'byUser':{
                'enabled': self.users_group.isChecked(),
                'users': users_list,
                'userkeys': userkeys_list,
            },
            'lookAt':{
                'enabled': self.looking_at_group.isChecked(),
                'lat':float(self.lat_widget.text() or '0'),
                'lon':float(self.lon_widget.text() or '0')
            },
            'onlyPanorama': self.onlyPanorama.isChecked()
        }
        for level in ['images','sequences','overview']:
            self.applySqlFilter(level)

    def getFilter(self):
        return self.filter

    def show(self, level):
        self.level = level
        super(mapillaryFilter, self).show()
        self.populateSearch()


    def applySqlFilter(self,level=None,layer=None):
        sqlFilter = ''
        if self.filter['byDate']['enabled']:
            sqlFilter += '("captured_at" > %d and "captured_at" < %d)' %(self.filter['byDate']['from'],self.filter['byDate']['to'])
        if self.filter['byUser']['enabled'] and self.filter['byUser']['userkeys']:
            if sqlFilter:
                sqlFilter += ' and '
            userkeys_list = ','.join(self.filter['byUser']['userkeys'])
            sqlFilter += '("userkey" in (%s))' % userkeys_list
        if self.filter['lookAt']['enabled'] and self.filter['lookAt']['lat'] and self.filter['lookAt']['lon']:
            bbox = "%f,%f,%f,%f" % (
                self.filter['lookAt']["lon"]-0.005,
                self.filter['lookAt']["lat"]-0.005,
                self.filter['lookAt']["lon"]+0.005,
                self.filter['lookAt']["lat"]+0.005,
            )
            lookat = '%f,%f' % (
                self.filter['lookAt']["lon"],
                self.filter['lookAt']["lat"],
            )
            res = self.mapillaryApi.images(bbox=bbox,lookat=lookat)
            if res:
                keys_looking_at = ""
                for feat in res["features"]:
                    keys_looking_at += "'%s'," % feat["properties"]["key"]
                if keys_looking_at:
                    if sqlFilter:
                        sqlFilter += ' and '
                    sqlFilter += '("key" in (%s))' % keys_looking_at[:-1]

        if self.filter['onlyPanorama']:
            if sqlFilter:
                sqlFilter += ' and '
            sqlFilter += '("pano" = 1)'

        if not layer:
            layer = getattr(self.module.coverage,level+'Layer')
        try:
            layer.setSubsetString(sqlFilter)
            layer.triggerRepaint()
        except:
            pass

    def closeEvent(self, event):
        self.closingPlugin.emit()
        event.accept()

    def populateSearch(self):
        layer = getattr(self.module.coverage, self.level + 'Layer')
        userkeys = []
        max = 0
        min_timestamp = sys.maxsize
        max_timestamp = 0
        for feat in layer.getFeatures():
            if feat['captured_at'] < min_timestamp:
                min_timestamp = feat['captured_at']
            if feat['captured_at'] > max_timestamp:
                max_timestamp = feat['captured_at']
            if max<100 and not feat['userkey'] in userkeys:
                userkeys.append(feat['userkey'])
                max += 1

        user_search = self.mapillaryApi.users(userkeys=','.join(userkeys))
        if user_search:
            usermap = {}
            for user in user_search:
                usermap[user['username']] = user['key']
            self.usersSearchFilter.clear()
            for user in sorted(usermap.keys()):
                self.usersSearchFilter.addItem(user, usermap[user])

            if not self.date_group.isChecked():
                mintime = QDateTime()
                mintime.setTime_t(min_timestamp/1000)
                self.fromDateWidget.setDateTime(mintime)
                maxtime = QDateTime()
                maxtime.setTime_t(max_timestamp/1000)
                self.toDateWidget.setDateTime(maxtime)

    def addUserAction(self):
        userCell = QtWidgets.QTableWidgetItem(self.usersSearchFilter.currentText())
        if userCell:
            userkeyCell = QtWidgets.QTableWidgetItem(self.usersSearchFilter.currentData())
            self.userFiltersTable.insertRow(self.userFiltersTable.rowCount())
            self.userFiltersTable.setItem(self.userFiltersTable.rowCount()-1,0,userCell)
            self.userFiltersTable.setItem(self.userFiltersTable.rowCount()-1,1,userkeyCell)


    def removeUserAction(self):
        if self.userFiltersTable.selectedItems():
            selected_rows = set()
            for item in self.userFiltersTable.selectedItems():
                selected_rows.add(item.row())
            for row_idx in list(selected_rows):
                self.userFiltersTable.removeRow(row_idx)

    def sampleOnCanvasAction(self):
        sampleTool = samplePointOnCanvas(self.iface.mapCanvas())
        sampleTool.pointClicked.connect(self.clickedOnCanvasAction)
        self.iface.mapCanvas().setMapTool(sampleTool)
        self.hide()

    def clickedOnCanvasAction(self,clickedPoint):
        self.iface.mapCanvas().setMapTool(self.module.mapSelectionTool)
        crsCanvas = self.module.iface.mapCanvas().mapSettings().destinationCrs() # get current crs
        crsWGS84 = QgsCoordinateReferenceSystem(4326)  # WGS 84
        xform = QgsCoordinateTransform(crsCanvas, crsWGS84, QgsProject.instance())
        wgs84point = xform.transform(clickedPoint)
        self.lon_widget.setText(str(wgs84point.x()))
        self.lat_widget.setText(str(wgs84point.y()))
        super(mapillaryFilter, self).show()
        self.raise_()


class samplePointOnCanvas(QgsMapTool):

    pointClicked = pyqtSignal(QgsPointXY)

    def canvasPressEvent(self, event):
        px = event.pos().x()
        py = event.pos().y()
        pressedPoint = QPoint(px, py)
        self.pointClicked.emit(self.toMapCoordinates(pressedPoint))