#!/usr/bin/env python
# --!-- coding: utf8 --!--
import re

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCursor, QFont, QFontMetrics
from PyQt5.QtWidgets import QAction, qApp, QToolTip, QTextEdit

from manuskript.ui.editors.completer import completer
from manuskript.ui.views.MDEditView import MDEditView
from manuskript.models import references as Ref


class MDEditCompleter(MDEditView):
    def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="",
                 autoResize=False):
        MDEditView.__init__(self, parent=parent, index=index, html=html, spellcheck=spellcheck, highlighting=True,
                              dict=dict, autoResize=autoResize)

        self.completer = None
        self.setMouseTracking(True)
        self.refRects = []
        self._noFocusMode = True

        self.textChanged.connect(self.getRefRects)
        self.document().documentLayoutChanged.connect(self.getRefRects)

    def setCurrentModelIndex(self, index):
        MDEditView.setCurrentModelIndex(self, index)
        if self._index and not self.completer:
            self.setCompleter(completer())

    def setCompleter(self, completer):
        self.completer = completer
        self.completer.activated.connect(self.insertCompletion)

    def insertCompletion(self, txt):
        tc = self.textCursor()
        tc.insertText(txt)
        self.setTextCursor(tc)

    def textUnderCursor(self, select=False):
        tc = self.textCursor()
        tc.select(QTextCursor.WordUnderCursor)
        if select:
            self.setTextCursor(tc)
        return tc.selectedText()

    def refUnderCursor(self, cursor):
        pos = cursor.position()
        cursor.select(QTextCursor.BlockUnderCursor)
        text = cursor.selectedText()
        pos -= cursor.selectionStart()
        match = re.findall(Ref.RegExNonCapturing, text)
        for m in match:
            if text.find(m) <= pos <= text.find(m) + len(m):
                return m

                # def event(self, event):
                # if event.type() == QEvent.ToolTip:
                # cursor = self.cursorForPosition(event.pos())
                # ref = self.refUnderCursor(cursor)
                # if ref:
                # QToolTip.showText(self.mapToGlobal(event.pos()), infoForRef(ref))
                # else:
                # QToolTip.hideText()
                # return True
                # return MDEditView.event(self, event)

    def createStandardContextMenu(self):
        menu = MDEditView.createStandardContextMenu(self)

        a = QAction(self.tr("Insert reference"), menu)
        a.triggered.connect(self.popupCompleter)
        menu.insertSeparator(menu.actions()[0])
        menu.insertAction(menu.actions()[0], a)
        return menu

    def keyPressEvent(self, event):
        if self.completer.isVisible():
            if event.key() in (
                    Qt.Key_Enter,
                    Qt.Key_Return,
                    Qt.Key_Escape,
                    Qt.Key_Tab,
                    Qt.Key_Backtab):
                event.ignore()
                return

        isShortcut = (event.modifiers() == Qt.ControlModifier and \
                      event.key() == Qt.Key_Space)

        if not self.completer or not isShortcut:
            self.completer.setVisible(False)
            MDEditView.keyPressEvent(self, event)
            return

        self.popupCompleter()

    def popupCompleter(self):
        if self.completer:
            cr = self.cursorRect()
            cr.moveTopLeft(self.mapToGlobal(cr.bottomLeft()))
            cr.setWidth(self.completer.sizeHint().width())
            self.completer.setGeometry(cr)
            self.completer.popup(self.textUnderCursor(select=True))

    def mouseMoveEvent(self, event):
        """
        When mouse moves, we show tooltip when appropriate.
        """
        self.beginTooltipMoveEvent()
        MDEditView.mouseMoveEvent(self, event)
        self.endTooltipMoveEvent()

        onRef = [r for r in self.refRects if r.contains(event.pos())]

        if not onRef:
            qApp.restoreOverrideCursor()
            self.hideTooltip()
            return

        cursor = self.cursorForPosition(event.pos())
        ref = self.refUnderCursor(cursor)
        if ref:
            if not qApp.overrideCursor():
                qApp.setOverrideCursor(Qt.PointingHandCursor)

            self.showTooltip(self.mapToGlobal(event.pos()), Ref.tooltip(ref))

    def mouseReleaseEvent(self, event):
        MDEditView.mouseReleaseEvent(self, event)
        onRef = [r for r in self.refRects if r.contains(event.pos())]
        if onRef:
            cursor = self.cursorForPosition(event.pos())
            ref = self.refUnderCursor(cursor)
            if ref:
                Ref.open(ref)
                qApp.restoreOverrideCursor()

    def resizeEvent(self, event):
        MDEditView.resizeEvent(self, event)
        self.getRefRects()

    def getRefRects(self):
        cursor = self.textCursor()
        f = self.font()
        f.setFixedPitch(True)
        f.setWeight(QFont.DemiBold)
        fm = QFontMetrics(f)
        refs = []
        for txt in re.finditer(Ref.RegEx, self.toPlainText()):
            cursor.setPosition(txt.start())
            r = self.cursorRect(cursor)
            r.setWidth(fm.width(txt.group(0)))
            refs.append(r)
        self.refRects = refs

    def paintEvent(self, event):
        QTextEdit.paintEvent(self, event)

        # Debug: paint rects
        # painter = QPainter(self.viewport())
        # painter.setPen(Qt.gray)
        # for r in self.refRects:
        # painter.drawRect(r)
