import re

from PyQt5 import uic
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QStyle, QStyleOption, QStylePainter

from blink.resources import Resources
from blink.util import translate
from blink.sessions import SMPVerification


__all__ = ['OTRWidget']


ui_class, base_class = uic.loadUiType(Resources.get('otr_widget.ui'))


class OTRWidget(base_class, ui_class):
    closed = pyqtSignal()
    nameChanged = pyqtSignal()
    statusChanged = pyqtSignal()

    color_table = {'green': 'hsv(100, 85%, 100%)', 'orange': 'hsv(20, 85%, 100%)'}

    def __init__(self, parent=None):
        super(OTRWidget, self).__init__(parent)
        with Resources.directory:
            self.setupUi(self)
        self.__dict__.update(peer_verified=False, smp_status=SMPVerification.Unavailable)  # interdependent properties (they need to preexist as their setters read each other)
        self.peer_name = ''
        self.peer_verified = False
        self.peer_fingerprint = ''
        self.my_fingerprint = ''
        self.smp_status = SMPVerification.Unavailable
        self.verification_stack.wrap = True
        self.verification_stack.animationDuration = 200
        self.close_button.clicked.connect(self.hide)
        self.switch_button.clicked.connect(self.verification_stack.slideInNext)
        self.peer_name_value.editingFinished.connect(self._check_name_changes)
        self.validate_button.clicked.connect(self._SH_ValidateButtonClicked)
        self.verification_stack.currentChanged.connect(self._SH_VerificationStackPanelChanged)

    @property
    def peer_name(self):
        return self.peer_name_value.text()

    @peer_name.setter
    def peer_name(self, name):
        self.__dict__['peer_name'] = name
        self.peer_name_value.setText(name)

    @property
    def peer_verified(self):
        return self.__dict__['peer_verified']

    @peer_verified.setter
    def peer_verified(self, verified):
        self.__dict__['peer_verified'] = verified
        self.validate_button.setText(translate('otr_widget', 'Invalidate') if verified else translate('otr_widget', 'Validate'))
        self.validate_button.setChecked(verified)
        self.validate_button.setEnabled(verified or self.verification_stack.currentWidget() is not self.smp_panel or self.smp_status is SMPVerification.Succeeded)
        self.peer_fingerprint_value.setStyleSheet('QLabel {{ color: {}; }}'.format(self.color_table['green'] if verified else self.color_table['orange']))
        self.smp_status_value.setText(self.smp_status_text)

    @property
    def peer_fingerprint(self):
        return self.__dict__['peer_fingerprint']

    @peer_fingerprint.setter
    def peer_fingerprint(self, fingerprint):
        self.__dict__['peer_fingerprint'] = fingerprint
        self.peer_fingerprint_value.setText(self._encode_fingerprint(fingerprint))

    @property
    def my_fingerprint(self):
        return self.__dict__['my_fingerprint']

    @my_fingerprint.setter
    def my_fingerprint(self, fingerprint):
        self.__dict__['my_fingerprint'] = fingerprint
        self.my_fingerprint_value.setText(self._encode_fingerprint(fingerprint))

    @property
    def smp_status(self):
        return self.__dict__['smp_status']

    @smp_status.setter
    def smp_status(self, status):
        self.__dict__['smp_status'] = status
        self.validate_button.setEnabled(self.peer_verified or self.verification_stack.currentWidget() is not self.smp_panel or self.smp_status is SMPVerification.Succeeded)
        self.smp_status_value.setText(self.smp_status_text)

    @property
    def smp_status_text(self):
        if self.peer_verified:
            return translate('otr_widget', '<span style="color: {[green]};">Verified</span>').format(self.color_table)
        elif self.smp_status is SMPVerification.Succeeded:
            return translate('otr_widget', '<span style="color: {[green]};">Succeeded</span>').format(self.color_table)
        elif self.smp_status is SMPVerification.Failed:
            return translate('otr_widget', '<span style="color: {[orange]};">Failed</span>').format(self.color_table)
        else:
            return '{}'.format(self.smp_status.value)

    def hideEvent(self, event):
        if not event.spontaneous():
            self.closed.emit()
            self._check_name_changes()

    def paintEvent(self, event):
        option = QStyleOption()
        option.initFrom(self)
        painter = QStylePainter(self)
        painter.setRenderHint(QStylePainter.Antialiasing, True)
        painter.drawPrimitive(QStyle.PE_Widget if self.testAttribute(Qt.WA_NoSystemBackground) else QStyle.PE_Frame, option)

    @staticmethod
    def _encode_fingerprint(fingerprint):
        return re.sub('....', lambda match: match.group(0) + {match.endpos: '', match.endpos//2: '<br/>'}.get(match.end(), ' '), fingerprint.encode().hex().upper())

    def _check_name_changes(self):
        peer_name = self.peer_name_value.text()
        if peer_name != self.__dict__['peer_name']:
            self.__dict__['peer_name'] = peer_name
            self.nameChanged.emit()

    def _SH_ValidateButtonClicked(self, checked):
        self.hide()
        self.peer_verified = checked
        self.statusChanged.emit()

    def _SH_VerificationStackPanelChanged(self, index):
        self.validate_button.setEnabled(self.peer_verified or self.verification_stack.currentWidget() is not self.smp_panel or self.smp_status is SMPVerification.Succeeded)

del ui_class, base_class