import math

import maya.cmds as cmds
import maya.OpenMaya as om

from PySide2.QtGui import QPainter, QPen, QPainterPath
from PySide2.QtCore import Qt, QObject, Signal, Slot, QEvent, QPointF, QPoint
from PySide2.QtWidgets import QWidget, QLabel, QGridLayout

import window_utils
import event_filter

class Canvas(QWidget):
    """ Canvas widget to draw on top of the viewport """
    def __init__(self, parent):
        super(Canvas, self).__init__(parent=parent)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.SplashScreen | Qt.WindowStaysOnTopHint | Qt.WindowTransparentForInput)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_NoSystemBackground)
        #  self.setAttribute(Qt.WA_PaintOnScreen)
        #  self.setAttribute(Qt.WA_TransparentForMouseEvents)

        self.canvas_event_filter = event_filter.CanvasEventFilter()
        self.install_event_filter()
        self.resize_event()
        self.show()

    def install_event_filter(self):
        """ install the resize evenet filter """

        self.canvas_event_filter.enter_event.connect(self.enter_widget)
        self.canvas_event_filter.leave_event.connect(self.leave_widget)
        self.canvas_event_filter.resize_event.connect(self.resize_event)
        view_wdg = window_utils.active_view_wdg()
        view_wdg.installEventFilter(self.canvas_event_filter)

    def remove_event_filter(self):
        """ clean up the resize evenet filter """

        view_wdg = window_utils.active_view_wdg()
        view_wdg.removeEventFilter(self.canvas_event_filter)

    @Slot(QEvent)
    def resize_event(self):
        """ resize the widget to match the viewport """

        view_wdg = window_utils.active_view_wdg()
        wdg_size = view_wdg.rect()
        wdg_pos = view_wdg.pos()
        abs_pos = view_wdg.mapToGlobal(wdg_pos)
        #  self.setGeometry(abs_pos.x(), abs_pos.y(), wdg_size.width(), wdg_size.height())
        self.resize(wdg_size.width(), wdg_size.height())
        self.move(abs_pos.x(), abs_pos.y())

    @Slot(QEvent)
    def enter_widget(self):
        """ set focuts to the panel under the cursor """

        panel = cmds.getPanel(underPointer=True)
        cmds.setFocus(panel)
        self.setFocus()

    @Slot(QEvent)
    def leave_widget(self):

        pass

    def __del__(self):
        """ remove event filter when the canvas is deleted """

        self.remove_event_filter()


""" -------------------------------------------------------------------- """
""" Brushes """
""" -------------------------------------------------------------------- """


class CircularBrush(Canvas):
    """ Draw a circular brush around the coursor
    based on the given brush state """

    def __init__(self, brush_state, parent):

        super(CircularBrush, self).__init__(parent=parent)
        self.brush_state = brush_state

    def paintEvent(self, event):

        super(CircularBrush, self).paintEvent(event)

        # draw brush
        if hasattr(self, 'brush_state') and self.brush_state.draw:
            painter = QPainter()
            shapes = self.create_brush_shape()
            for shape in shapes:
                shape = [QPointF(point[0], point[1]) for point in shape]

                path = QPainterPath()
                start_pos = shape.pop(0)
                path.moveTo(start_pos)
                [path.lineTo(point) for point in shape]

                painter.setRenderHint(painter.Antialiasing)
                #  painter.setRenderHint(painter.HighQualityAnti)
                painter.begin(self)

                painter.setPen(QPen(Qt.red, 1))
                painter.drawPath(path)

            painter.end()


    def create_brush_shape(self):
        """ generate the shape of the brush based on the brush state """

        if self.brush_state.draw:
            # fetch point and normal
            pnt = om.MPoint(self.brush_state.position[0],
                            self.brush_state.position[1],
                            self.brush_state.position[2])
            nrm = om.MVector(self.brush_state.normal[0],
                            self.brush_state.normal[1],
                            self.brush_state.normal[2])
            tan = om.MVector(self.brush_state.tangent[0],
                            self.brush_state.tangent[1],
                            self.brush_state.tangent[2])

            # get point at normal and tangent
            #  n_pnt = pnt + (nrm * self._state.radius * 0.75)
            #  t_str = pnt + (tan * self._state.radius * 0.75)
            #  t_end = pnt + (tan * self._state.radius)
            #  shape.append(window_utils.world_to_view(pnt))

            shape = []
            # get circle points
            theta = math.radians(360 / 20)
            for i in xrange(40 + 1):
                rot = om.MQuaternion(theta * i, nrm)
                rtan = tan.rotateBy(rot)
                pos = pnt + (rtan * self.brush_state.radius)

                pos_x, pos_y = window_utils.world_to_view(pos)
                shape.append((pos_x, pos_y))

            return [shape]


class HelpDisplay(Canvas):

    key_mapping = {'place': {'Shift': 'Drag',
                             'Ctrl': 'Align to Stroke'},
                   'spray': {'Shift': 'Drag',
                             'Ctrl': 'Align to Stroke',
                             'b': 'Modify Radius'},
                   'scale': {'Shift': 'Smooth Scale',
                             'Ctrl': 'Randomize Scale'},
                   'align': {'Shift': 'Smooth Align (Not implemented yet)',
                             'Ctrl': 'Randomize Align'},
                   'move': {'None': ''},
                   'id': {'Ctrl': 'Pick Random'},
                   'remove': {'Shift': 'Restore',
                              'Ctrl': 'Random Delete'}}

    def __init__(self, mode, parent):
        super(HelpDisplay, self).__init__(parent=parent)

        #  self.setWindowFlags(Qt.FramelessWindowHint | Qt.SplashScreen | Qt.WindowStaysOnTopHint | Qt.WindowTransparentForInput)
        self.mapping = self.key_mapping[mode]
        self.mode = mode
        self.visible = True
        self.build()

    def build(self):

        self.setStyleSheet('QLabel {color: white}')

        layout = QGridLayout()
        self.setLayout(layout)

        layout.setRowStretch(0, 10)
        layout.setColumnStretch(3, 1)

        key_lbl = QLabel('{} Hotkeys:'.format(self.mode.title()))
        layout.addWidget(key_lbl, 1, 0, 1, 2)

        position = 2
        for key, op in self.mapping.iteritems():

            key_lbl = QLabel(key)
            layout.addWidget(key_lbl, position, 0, 1, 1)

            op_lbl = QLabel(op)
            layout.addWidget(op_lbl, position, 1, 1, 1)

            position += 1

        #  help_key_lbl = QLabel('h')
        #  layout.addWidget(help_key_lbl, position, 0, 1, 1)
        #
        #  help_lbl = QLabel('Toggle Help')
        #  layout.addWidget(help_lbl, position, 1, 1, 1)

        layout.setRowStretch(position, 1)

    def set_visible(self, visible):
        if self.visible is not visible:
            self.setVisible(visible)
            self.visible = visible
            self.update()