# -*- coding: UTF-8 -*-
import os
from collections import OrderedDict

from PyQt5.QtWidgets import (
    QDialog, QAbstractItemView, QVBoxLayout, QHBoxLayout, QLabel, QWidget,
    QTreeView, QLineEdit, QTableView, QCompleter
)
from PyQt5.QtGui import QStandardItem, QStandardItemModel, QPixmap
from PyQt5.QtCore import Qt, pyqtSlot, QModelIndex

from .qt_models import get_simple_model
from .forms import GridForm
from .buttons import ActionButton

__all__ = ['QuickDialog', 'SearchDialog', 'HelpDialog', 'FactoryIcons']

current_dir = os.path.dirname(__file__)

_SIZE = (500, 200)


class QuickDialog(QDialog):

    def __init__(self, parent, kind, string=None, data=None, widgets=None,
                 icon=None, size=None, readonly=False):
        super(QuickDialog, self).__init__(parent)
        # Size arg is in deprecation
        if not size:
            size = _SIZE
        self.factory = None
        self.readonly = readonly
        self.parent = parent
        self.parent_model = None
        titles = {
            'warning': self.tr('Warning...'),
            'info': self.tr('Information...'),
            'action': self.tr('Action...'),
            'help': self.tr('Help...'),
            'error': self.tr('Error...'),
            'question': self.tr('Question...'),
            'selection': self.tr('Selection...'),
            None: self.tr('Dialog...')
        }
        self.setWindowTitle(titles[kind])
        self.setModal(True)
        self.setParent(parent)
        self.factory = FactoryIcons()
        self.default_widget_focus = None
        self.kind = kind
        self.widgets = widgets
        self.data = data
        string_widget = None
        data_widget = None
        _buttons = None
        row_stretch = 1
        main_vbox = QVBoxLayout()

        self.sub_hbox = QHBoxLayout()

        # Add main message
        if string:
            # For simple dialog
            string_widget = QLabel(string)

        if kind == 'help':
            data_widget = widgets[0]
        elif kind == 'action':
            if widgets:
                data_widget = widgets[0]
            elif data:
                data_widget = GridForm(parent, OrderedDict(data))
        elif kind == 'selection':
            self.name = data['name']
            data_widget = self.set_selection(parent, data)
        elif widgets:
            data_widget = GridForm(parent, OrderedDict(widgets))

        if string_widget:
            main_vbox.addWidget(string_widget, 0)

        if data_widget:
            if isinstance(data_widget, QWidget):
                row_stretch += 1
                size = (size[0], size[1] + 200)
                self.sub_hbox.addWidget(data_widget, 0)
            else:
                self.sub_hbox.addLayout(data_widget, 0)

        self.ok_button = ActionButton('ok', self.dialog_accepted)
        self.ok_button.setFocus()
        self.ok_button.setDefault(True)
        self.cancel_button = ActionButton('cancel', self.dialog_rejected)

        _buttons = []
        if kind in ('info', 'help', 'warning', 'question', 'error'):
            if kind in ('warning', 'question'):
                _buttons.append(self.cancel_button)
            _buttons.append(self.ok_button)
        elif kind in ('action', 'selection'):
            _buttons.extend([self.cancel_button, self.ok_button])

        self.buttonbox = QHBoxLayout()
        for b in _buttons:
            self.buttonbox.addWidget(b, 1)

        main_vbox.addLayout(self.sub_hbox, 1)
        main_vbox.addLayout(self.buttonbox, 1)
        main_vbox.insertStretch(row_stretch, 0)

        self.setLayout(main_vbox)
        self.setSizeGripEnabled(True)

        if kind in ('info', 'error'):
            self.show()

    def exec_(self, args=None):
        res = None
        res = super(QuickDialog, self).exec()
        if self.kind == 'action':
            pass
        return res

    def show(self):
        super(QuickDialog, self).show()
        # self.parent.releaseKeyboard()
        self.ok_button.setFocus()
        if self.default_widget_focus:
            self.default_widget_focus.setFocus()
            if hasattr(self.default_widget_focus, 'setText'):
                self.default_widget_focus.setText('')
        else:
            self.setFocus()

    def hide(self):
        super(QuickDialog, self).hide()
        self.parent.setFocus()

    def add_widget(self, widget):
        _ = self.sub_hbox.takeAt(0)
        self.sub_hbox.addLayout(widget, 0)

    def set_info(self, info):
        if hasattr(self, 'label_info'):
            self.label_info.setText(info)

    def set_widgets(self, widgets):
        if widgets:
            # Set default focus to first widget created
            self.default_widget_focus = widgets[0]

    def closeEvent(self, event):
        super(QuickDialog, self).closeEvent(event)

    def dialog_rejected(self):
        self.parent.setFocus()
        self.setResult(0)
        self.hide()

    def dialog_accepted(self):
        if self.kind in ('action', 'selection', 'warning', 'question'):
            self.setResult(1)
            self.done(1)
        self.hide()

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_Escape:
            self.dialog_rejected()
        else:
            super(QuickDialog, self).keyPressEvent(event)

    def set_selection(self, obj, data):
        self.set_simple_model()
        setattr(obj, data['name'] + '_model', self.data_model)
        self.parent_model = data.get('parent_model')
        self.treeview = QTreeView()
        self.treeview.setRootIsDecorated(False)
        self.treeview.setColumnHidden(0, True)
        self.treeview.setItemsExpandable(False)
        self.treeview.setAlternatingRowColors(True)
        self.treeview.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.treeview.setModel(self.data_model)
        self.treeview.clicked.connect(self.field_selection_changed)
        self.treeview.activated.connect(self.field_selection_changed)

        self.update_values(self.data['values'])

        # By default first row must be selected
        item = self.data_model.item(0, 0)
        idx = self.data_model.indexFromItem(item)
        self.treeview.setCurrentIndex(idx)
        return self.treeview

    def update_values(self, values):
        self.data_model.removeRows(0, self.data_model.rowCount())
        self._insert_items(self.data_model, values)
        self.treeview.resizeColumnToContents(0)

    def set_simple_model(self):
        self.data_model = QStandardItemModel(0, len(self.data['heads']), self)
        _horizontal = Qt.Horizontal
        for i, h in enumerate(self.data['heads'], 0):
            self.data_model.setHeaderData(i, _horizontal, h)

    def _insert_items(self, model, values):
        for value in values:
            row = []
            for v in value:
                itemx = QStandardItem(v)
                itemx.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                row.append(itemx)
            self.data_model.insertRow(0, row)
        self.data_model.sort(0, Qt.AscendingOrder)

    @pyqtSlot(QModelIndex)
    def field_selection_changed(self, qm_index):
        if not self.readonly:
            item_id = self.data_model.item(qm_index.row(), 0).text()
            item_name = self.data_model.item(qm_index.row(), 1).text()

            if self.parent_model is not None:
                self.parent_model[self.name] = item_id
            if hasattr(self.parent, 'field_' + self.name):
                field = getattr(self.parent, 'field_' + self.name)
                if hasattr(field, 'setText'):
                    field.setText(item_name)
            else:
                setattr(self.parent, 'field_' + self.name + '_name', item_name)
            setattr(self.parent, 'field_' + self.name + '_id', int(item_id))
            action = getattr(self.parent, 'action_' + self.name + '_selection_changed')
            action()
        self.dialog_accepted()


class SearchDialog(QDialog):

    def __init__(self, parent, headers, values, on_activated,
            hide_headers=False, completion_column=None, title=None):
        super(SearchDialog, self).__init__(parent)
        self.parent = parent
        self.headers = headers
        self.values = values
        if not title:
            title = self.tr('Search Products...')
        self.setWindowTitle(title)

        self._product_line = QLineEdit()
        self.table_view = QTableView()

        button_cancel = ActionButton('cancel', self.on_reject)
        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        hbox.addWidget(button_cancel)
        vbox.addWidget(self._product_line)
        vbox.addLayout(hbox)
        self.setLayout(vbox)
        self.completer = QCompleter()
        self.treeview_search_product = QTreeView()
        if hide_headers:
            col_headers = self.treeview_search_product.header()
            col_headers.hide()
        self.completer.setPopup(self.treeview_search_product)
        self._product_line.setCompleter(self.completer)
        self.set_model()

        self.completer.activated.connect(self.on_accept)
        self.completer.setFilterMode(Qt.MatchStartsWith)
        self.completer.setCaseSensitivity(Qt.CaseInsensitive)
        self.completer.setCompletionColumn(2)
        self.completer.activated.connect(on_activated)

    def set_model(self):
        headers_name = [h[1] for h in self.headers]
        self.model = get_simple_model(self.parent, self.values, headers_name)
        self.completer.setModel(self.model)

    def get_selected_index(self):
        model_index = self._get_model_index()
        idx = self.model.index(model_index.row(), 0)
        return idx.data()

    def get_selected_data(self):
        model_index = self._get_model_index()
        data = {}
        i = 0
        for h, _ in self.headers:
            data[h] = self.model.index(model_index.row(), i).data()
            i += 1
        return data

    def _get_model_index(self):
        item_view = self.completer.popup()
        index = item_view.currentIndex()
        proxy_model = self.completer.completionModel()
        model_index = proxy_model.mapToSource(index)
        return model_index

    def on_accept(self):
        self.accept()

    def on_reject(self):
        self.reject()


class HelpDialog(QuickDialog):

    def __init__(self, parent):
        self.treeview = QTreeView()
        self.treeview.setRootIsDecorated(False)
        self.treeview.setAlternatingRowColors(True)
        self.treeview.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.treeview.setEditTriggers(QAbstractItemView.NoEditTriggers)
        super(HelpDialog, self).__init__(parent, 'help', widgets=[self.treeview],
            size=(400, 500))
        self.set_info(self.tr('Keys Shortcuts...'))
        self.hide()

    def set_shortcuts(self, shortcuts):
        model = self._help_model(shortcuts)
        self.treeview.setModel(model)
        header = self.treeview.header()
        header.resizeSection(0, 250)

    def _help_model(self, shortcuts):
        model = QStandardItemModel(0, 2, self)
        model.setHeaderData(0, Qt.Horizontal, self.tr('Action'))
        model.setHeaderData(1, Qt.Horizontal, self.tr('Shortcut'))

        for short in shortcuts:
            model.insertRow(0)
            model.setData(model.index(0, 0), short[0])
            model.setData(model.index(0, 1), short[1])
        return model


class FactoryIcons(object):

    def __init__(self):
        name_icons = ['print', 'warning', 'info', 'error', 'question']
        self.icons = {}
        for name in name_icons:
            path_icon = os.path.join(current_dir, '..', 'share', 'icon-' + name + '.png')
            if not os.path.exists(path_icon):
                continue
            _qpixmap_icon = QPixmap()
            _qpixmap_icon.load(path_icon)
            _icon_label = QLabel()
            _icon_label.setAlignment(Qt.AlignCenter | Qt.AlignCenter)
            _icon_label.setPixmap(_qpixmap_icon.scaledToHeight(48))
            self.icons[name] = _icon_label
