# -*- coding: utf-8 -*-
#
# Copyright 2016 Continuum Analytics, Inc.
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
#

"""
Helper widgets.
"""

from __future__ import absolute_import, division, print_function

# Third party imports
from qtpy import PYQT4
from qtpy.compat import getexistingdirectory, getopenfilename
from qtpy.QtCore import Qt, QRegExp, Signal
from qtpy.QtGui import QRegExpValidator
from qtpy.QtWidgets import (QCheckBox, QHBoxLayout, QLabel, QLineEdit,
                            QMessageBox, QPushButton, QSpacerItem,
                            QVBoxLayout, QWidget,
                            )
from conda_manager.widgets.helperwidgets import LineEditSearch
import qtawesome as qta


class MessageCheckBox(QMessageBox):
    """
    A QMessageBox derived widget that includes a QCheckBox aligned to the
    right under the message and on top of the buttons.
    """
    def __init__(self, *args, **kwargs):
        super(MessageCheckBox, self).__init__(*args, **kwargs)

        self._checkbox = QCheckBox()

        # Set layout to include checkbox
        size = 9
        check_layout = QVBoxLayout()
        check_layout_h = QHBoxLayout()
        check_layout.addItem(QSpacerItem(size, size))
        check_layout_h.addStretch()
        check_layout_h.addWidget(self._checkbox, 1, Qt.AlignRight)
        check_layout.addLayout(check_layout_h)
        check_layout.addItem(QSpacerItem(size, size))

        # Access the Layout of the MessageBox to add the Checkbox
        layout = self.layout()

        if PYQT4:
            grid_position = 1
        else:
            grid_position = 2

        layout.addLayout(check_layout, 1, grid_position)

    # --- Public API
    # Methods to access the checkbox
    def is_checked(self):
        return self._checkbox.isChecked()

    def set_checked(self, value):
        return self._checkbox.setChecked(value)

    def set_check_visible(self, value):
        self._checkbox.setVisible(value)

    def is_check_visible(self):
        self._checkbox.isVisible()

    def checkbox_text(self):
        self._checkbox.text()

    def set_checkbox_text(self, text):
        self._checkbox.setText(text)

    @staticmethod
    def _boxcreator(parent, title, text, buttons=QMessageBox.Ok,
                    defaultButton=QMessageBox.NoButton, checkbox_text='',
                    icon=None):
        widget = MessageCheckBox(icon, title, text, buttons=buttons,
                                 parent=parent)
        widget.set_checkbox_text(checkbox_text)
        return widget

    @staticmethod
    def warning(*args, **kwargs):
        kwargs['icon'] = QMessageBox.Warning
        return MessageCheckBox._boxcreator(*args, **kwargs)

    @staticmethod
    def critical(*args, **kwargs):
        kwargs['icon'] = QMessageBox.Critical
        return MessageCheckBox._boxcreator(*args, **kwargs)

    @staticmethod
    def information(*args, **kwargs):
        kwargs['icon'] = QMessageBox.Information
        return MessageCheckBox._boxcreator(*args, **kwargs)

    @staticmethod
    def question(*args, **kwargs):
        kwargs['icon'] = QMessageBox.Question
        return MessageCheckBox._boxcreator(*args, **kwargs)


class EditableLineEdit(QWidget):
    """
    """
    sig_text_changed = Signal(object, object)  # old_text, new_text

    def __init__(self, title, text, regex=None, allow_empty=False):
        super(EditableLineEdit, self).__init__()
        self._label = QLabel(title)
        self._text = QLineEdit()
        self.button_edit = QPushButton()
        self.allow_empty = allow_empty
        self.regex = regex
        self.qregex = None

        self.button_edit.setIcon(qta.icon('fa.edit'))
        self._text.setText(text)

        layout = QVBoxLayout()
        layout.addWidget(self._label)

        layout_h = QHBoxLayout()
        layout_h.addWidget(self._text)
        layout_h.addWidget(self.button_edit)
        layout.addLayout(layout_h)

        self.setLayout(layout)
        self._text.setDisabled(True)

        self.button_edit.clicked.connect(self.edit)

        self.last_text = self._text.text()
        self.set_regex(regex)

#    def focusOutEvent(self, event):
#        """
#        Qt override.
#        FIXME:
#        """
#        super(EditableLineEdit, self).focusOutEvent(event)
#        event = QKeyEvent(QKeyEvent.KeyPress, Qt.Key_Escape)
#        self.keyPressEvent(event)

    def keyPressEvent(self, event):
        """
        Qt override.
        """
        super(EditableLineEdit, self).keyPressEvent(event)
        key = event.key()
        if key in [Qt.Key_Enter, Qt.Key_Return]:
            self.check_text()
        elif key in [Qt.Key_Escape]:
            self._text.setText(self.last_text)
            self.check_text(escaped=True)

    # --- Public API
    # -------------------------------------------------------------------------
    def text(self):
        return self._text.text()

    def setText(self, text):
        self.set_text(text)

    def set_text(self, text):
        """
        """
        self._text.setText(text)

    def set_label_text(self, text):
        """
        """
        self.label.setText(text)

    def set_regex(self, regex):
        """
        """
        if regex:
            self.regex = regex
            self.qregex = QRegExp(regex)
            validator = QRegExpValidator(self.qregex)
            self._text.setValidator(validator)

    def check_text(self, escaped=False):
        """
        """
        self._text.setDisabled(True)
        self.button_edit.setDisabled(False)
        new_text = self._text.text()

        if not self.allow_empty and len(new_text) == 0:
            self.edit()

        if self.last_text != new_text and not escaped:
            self.sig_text_changed.emit(self.last_text, new_text)
            self.last_text = new_text

    def edit(self):
        """
        """
        self._text.setDisabled(False)
        self.button_edit.setDisabled(True)
        self._text.setFocus()
        self._text.setCursorPosition(len(self._text.text()))
        self.last_text = self._text.text()


class EditablePathEdit(EditableLineEdit):
    """
    """
    def __init__(self, title, text, basedir=None, fileselect=False,
                 caption='', filters='', selected_filter=''):
        super(EditablePathEdit, self).__init__(title, text)
        self.basedir = basedir
        self.fileselect = fileselect
        self.filters = filters
        self.selected_filter = selected_filter
        self.caption = caption

    def set_directory(self, basedir):
        """
        """
        self.basedir = basedir

    def edit(self):
        """
        """
        if self.fileselect:
            path, filter_ = getopenfilename(
                basedir=self.basedir,
                caption=self.caption,
                filters=self.filters,
                selectedfilter=self.selected_filter)
        else:
            path = getexistingdirectory(basedir=self.basedir,
                                        caption=self.caption)

        if path:
            self._text.setText(path)
            if path != self.last_text:
                self.sig_text_changed.emit(self.last_text, path)
            self.last_text = self._text.text()


def test():
    from anaconda_navigator.utils.qthelpers import qapplication
    from anaconda_navigator.config import get_home_dir
    app = qapplication()

    w1 = EditableLineEdit('Project name', 'my-project',
                          regex='[A-Za-z0-9_\- ]{1,20}')
    w1.show()

    w2 = EditablePathEdit('Icon', '',
                          basedir=get_home_dir(),
                          fileselect=True,
                          caption='Select icon file',
                          filters="Image files (*.png *.jpg)")
    w2.show()

    w3 = MessageCheckBox.warning(
        None,
        'Delete project',
        'Do you really want to delete project {0}?'.format(''),
        checkbox_text='Delete project files',
        buttons=MessageCheckBox.Yes | MessageCheckBox.No,
        )
    reply = w3.exec_()
    print(reply, w3.is_checked())
    app.exec_()


if __name__ == '__main__':
    test()
