# -*- coding: utf-8 -*-
"""
/***************************************************************************
 QRectangleCreator
                                 A QGIS plugin
 Plugin to create polygon
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2019-05-16
        git                  : https://github.com/abocianowski/QRectangleCreator
        copyright            : (C) 2019 by Adrian Bocianowski
        email                : adrian@bocianowski.com.pl
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""
from .resources import *

from PyQt5.QtCore import QSettings, QTranslator, qVersion, QCoreApplication, QPoint
from PyQt5.QtGui import QIcon, QColor
from PyQt5.QtWidgets import QAction, QToolButton,QMenu
from PyQt5 import uic
from PyQt5 import QtWidgets

from qgis.gui import QgsMapToolEmitPoint, QgsRubberBand, QgsMapCanvas, QgsVertexMarker
from qgis.core import QgsWkbTypes,QgsPoint, QgsGeometry, QgsPointXY, QgsPointLocator, QgsFeature, QgsCoordinateTransform, QgsCoordinateReferenceSystem, QgsProject


import math
from pyproj import Proj, transform
import os


class QRectangleCreator:
    def __init__(self, iface):
        self.iface = iface
        self.plugin_dir = os.path.dirname(__file__)
        locale = QSettings().value('locale/userLocale')[0:2]
        locale_path = os.path.join(
            self.plugin_dir,
            'i18n',
            'qrectanglecreator_{}.qm'.format(locale))

        if os.path.exists(locale_path):
            self.translator = QTranslator()
            self.translator.load(locale_path)

            if qVersion() > '4.3.3':
                QCoreApplication.installTranslator(self.translator)

        self.actions = []
        self.menu = self.tr(u'&QRectangleCreator')
        self.toolsToolbar = self.iface.addToolBar(u'QRectangle Creator')
        self.toolsToolbar.setObjectName(u'QRectangle Creator')
        self.settingsDlg = SettingsDialog()
        self.settingsDlg.width.valueChanged.connect(self.settingsChanged)
        self.settingsDlg.height.valueChanged.connect(self.settingsChanged)
        self.settingsDlg.angle.valueChanged.connect(self.settingsChanged)
        self.first_start = None

    def tr(self, message):
        return QCoreApplication.translate('QRectangleCreator', message)

    def add_action(
        self,
        icon_path,
        text,
        callback,
        enabled_flag=True,
        add_to_menu=True,
        add_to_toolbar=True,
        status_tip=None,
        whats_this=None,
        parent=None,
        checkable=False,
        checked=False,
        shortcut=None):

        icon = QIcon(icon_path)
        action = QAction(icon, text, parent)
        action.triggered.connect(callback)
        action.setEnabled(enabled_flag)

        if status_tip is not None:
            action.setStatusTip(status_tip)

        if whats_this is not None:
            action.setWhatsThis(whats_this)

        if add_to_toolbar:
            self.toolsToolbar.addAction(action)

        if add_to_menu:
            self.iface.addPluginToMenu(
                self.menu,
                action)

        if checkable:
            action.setCheckable(True)
            
        if checked:
            action.setChecked(1)

        if shortcut:
            action.setShortcut(shortcut)

        self.actions.append(action)

        return action

    def initGui(self):

        icon_path = ':/plugins/QRectangleCreator/icons/'

        #LoginButton
        self.mainButton = QToolButton()
        self.mainButton.setIcon(QIcon(icon_path + 'addRectangle.png'))
        self.mainButton.setPopupMode(QToolButton.MenuButtonPopup)
        self.mainButton.clicked.connect(self.run)
        self.mainButton.setToolTip('Add Rectangle')
        self.mainButton.setEnabled(True)
        self.mainButton.setCheckable(True)
        self.mainButton.setMenu(QMenu())
        self.toolsToolbar.addWidget(self.mainButton)

        #SettingsButton
        self.SettingsButton = self.add_action(
                icon_path + 'addRectangle.png',
                text=self.tr(u'Settings'),
                callback=self.settings,
                parent=self.iface.mainWindow(),
                add_to_menu=False,
                enabled_flag = False,
                add_to_toolbar = False)
        m = self.mainButton.menu()
        m.addAction(self.SettingsButton)

        self.first_start = True

    def unload(self):
        for action in self.actions:
            self.iface.removePluginMenu(
                self.tr(u'&QRectangleCreator'),
                action)
            self.iface.removeToolBarIcon(action)

    def run(self):
        if self.first_start == True:
            self.first_start = False

        if self.mainButton.isChecked()==1:
            self.drawingObject = StartDrawing(self.iface.mapCanvas(),self.iface)
            self.drawingObject.setConfiguration(
                    self.settingsDlg.width.value(),
                    self.settingsDlg.height.value(),
                    self.settingsDlg.angle.value())
            self.iface.mapCanvas().setMapTool(self.drawingObject) 
            self.SettingsButton.setEnabled(True)
        else:
            self.iface.mapCanvas().unsetMapTool(self.drawingObject) 
            self.drawingObject.reset()
            self.SettingsButton.setEnabled(False)

    def settings(self):
        self.settingsDlg.show()
        current_width = self.settingsDlg.width.value()
        current_height = self.settingsDlg.height.value()
        current_angle = self.settingsDlg.angle.value()
        
        if self.settingsDlg.exec_() != 1:
            self.settingsDlg.width.setValue(current_width)
            self.settingsDlg.height.setValue(current_height)
            self.settingsDlg.angle.setValue(current_angle)

    def settingsChanged(self):
        self.drawingObject.setConfiguration(
                    self.settingsDlg.width.value(),
                    self.settingsDlg.height.value(),
                    self.settingsDlg.angle.value())

class StartDrawing(QgsMapToolEmitPoint):
    def __init__(self, canvas, iface):
        QgsMapToolEmitPoint.__init__(self, canvas)

        # qgis interface
        self.canvas = canvas
        self.iface = iface

        # snap marker
        self.snap_mark = QgsVertexMarker(self.canvas)
        self.snap_mark.setColor(QColor(0, 0, 255))
        self.snap_mark.setPenWidth(2)
        self.snap_mark.setIconType(QgsVertexMarker.ICON_BOX)
        self.snap_mark.setIconSize(10)
        
        # rectangle
        self.rubberBand = QgsRubberBand(self.canvas, QgsWkbTypes.GeometryType(3))
        self.rubberBand.setWidth(3)
        self.rubberBand.setStrokeColor(QColor(254,0,0))
        
        # initialize variable
        self.rubberBand_width = 0
        self.rubberBand_height = 0
        self.rubberBand_angle = 0

        self.reset()
    
    def setConfiguration(self,width,height,angle):
        self.rubberBand_width = width
        self.rubberBand_height = height
        self.rubberBand_angle = angle


    def reset(self):
        self.rubberBand.reset(QgsWkbTypes.GeometryType(3))
        self.isEmittingPoint = False
        
    def canvasMoveEvent( self, e ):
        self.snap_mark.hide()
        self.snapPoint = False
        self.rubberBand.reset(QgsWkbTypes.GeometryType(3))

        self.snapPoint = self.checkSnapToPoint(e.pos())

        if self.snapPoint[0]:
            self.snap_mark.setCenter(self.snapPoint[1])
            self.snap_mark.show()
            self.rectangle = self.getRectangle(self.snapPoint[1])
            self.rubberBand.setToGeometry(self.rectangle, None)
            self.rubberBand.show()

        else:
            self.rectangle = self.getRectangle(self.toMapCoordinates(e.pos()))
            self.rubberBand.setToGeometry(self.rectangle, None)
            self.rubberBand.show()

    def checkSnapToPoint(self, point):
        snapped = False
        snap_point = self.toMapCoordinates(point)
        snapper = self.canvas.snappingUtils()
        snapMatch = snapper.snapToMap(point)
        if snapMatch.hasVertex():
            snap_point = snapMatch.point()
            snapped = True
        return snapped, snap_point

    def canvasPressEvent(self, e):
        if self.snapPoint == False:
            point = self.toMapCoordinates(self.canvas.mouseLastXY())
        else:
            point = self.snapPoint[1]
        
        layer = self.iface.activeLayer()

        layer_crs = layer.crs().authid()
        layer_crs = QgsCoordinateReferenceSystem(layer_crs)
        canvas_crs = self.canvas.mapSettings().destinationCrs().authid()
        canvas_crs = QgsCoordinateReferenceSystem(canvas_crs)
        crs2crs = QgsCoordinateTransform(canvas_crs, layer_crs, QgsProject.instance())

        feature = QgsFeature()
        fields = layer.fields()
        feature.setFields(fields)

        if layer.wkbType() == QgsWkbTypes.Polygon or layer.wkbType() == QgsWkbTypes.MultiPolygon :
            if layer_crs == canvas_crs:
                feature.setGeometry( self.rectangle)
            else:
                geom = self.rectangle
                geom.transform(crs2crs)
                feature.setGeometry( geom)
                
            layer.startEditing()
            layer.addFeature(feature)
            layer.commitChanges()
            layer.reload()
        else:
            self.iface.messageBar().pushCritical ('QRectangle Creator: ','The current layer is not of Polygon or MultiPolygon type. The object has not been added')

        


    def getRectangle(self,point):
        polygon = QgsWkbTypes.GeometryType(3)

        x = point.x()
        y = point.y()

        points = [[
                QgsPointXY( # Left Top corner
                    x - (self.rubberBand_width/2),
                    y + (self.rubberBand_height/2)
                ),
                QgsPointXY( # Right Top corner
                    x + (self.rubberBand_width/2),
                    y + (self.rubberBand_height/2)
                ),
                QgsPointXY( # Right Down corner
                    x + (self.rubberBand_width/2),
                    y - (self.rubberBand_height/2)
                ),
                QgsPointXY( # Left Down corner
                    x - (self.rubberBand_width/2),
                    y - (self.rubberBand_height/2)
                )
                ]]
        polygon = QgsGeometry.fromPolygonXY(points)
        polygon.rotate(self.rubberBand_angle,point)
        return polygon

FORM_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'settings.ui'))
class SettingsDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        super(SettingsDialog, self).__init__(parent)
        self.setupUi(self)

    

        
