# -*- coding: utf-8 -*-
import re

from natsort import natsorted
from PyQt5 import QtWidgets, QtCore

from ..ui import resource_rc as resource_rc
from ..ui.multi_search_dialog import Ui_MultiSearchDialog


class MultiSearch(Ui_MultiSearchDialog, QtWidgets.QDialog):
    def __init__(self, channels_dbs, tooltips, *args, **kwargs):

        super().__init__(*args, **kwargs)
        self.setupUi(self)
        self.setWindowFlags(
            self.windowFlags()
            | QtCore.Qt.WindowSystemMenuHint
            | QtCore.Qt.WindowMinMaxButtonsHint
        )

        self.result = set()
        self.channels_dbs = channels_dbs

        description_template = '<html><head/><body><p><span style=" font-size:10pt; font-weight:400;">{}</span></p><p><span style=" font-size:8pt; font-weight:300;">{}</span></p></body></html>'

        self.match_lists = []
        for channels_db, tooltip in zip(self.channels_dbs, tooltips):
            vbox = QtWidgets.QVBoxLayout()
            description = QtWidgets.QTextEdit()
            sizePolicy = QtWidgets.QSizePolicy(
                QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed
            )
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(1)
            sizePolicy.setHeightForWidth(description.sizePolicy().hasHeightForWidth())
            description.setSizePolicy(sizePolicy)
            description.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
            description.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            description.setSizeAdjustPolicy(
                QtWidgets.QAbstractScrollArea.AdjustToContents
            )
            description.setText(description_template.format(*tooltip.splitlines()))
            description.setReadOnly(True)

            vbox.addWidget(description)
            lst = QtWidgets.QListWidget()
            self.match_lists.append(lst)

            lst.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
            lst.setToolTip(tooltip)
            lst.setMinimumSize(QtCore.QSize(400, 0))
            vbox.addWidget(lst)
            vbox.setStretch(0, 0)
            vbox.setStretch(1, 1)
            self.match_layout.addLayout(vbox)

        self.apply_btn.clicked.connect(self._apply)
        self.add_btn.clicked.connect(self._add)
        self.cancel_btn.clicked.connect(self._cancel)

        self.search_box.editingFinished.connect(self.search_text_changed)
        self.match_kind.currentTextChanged.connect(self.search_box.textChanged.emit)

        self.setWindowTitle("Search & select channels")
        self.add_btn.setFocus()

    def search_text_changed(self):
        text = self.search_box.text().strip()
        if len(text) >= 2:
            if self.match_kind.currentText() == "Wildcard":
                pattern = text.replace("*", "_WILDCARD_")
                pattern = re.escape(pattern)
                pattern = pattern.replace("_WILDCARD_", ".*")
            else:
                pattern = text

            try:
                pattern = re.compile(f"(?i){pattern}")
                for i, (channels_db, matches) in enumerate(
                    zip(self.channels_dbs, self.match_lists)
                ):
                    match_results = [
                        name for name in channels_db if pattern.match(name)
                    ]
                    matches.clear()
                    matches.addItems(match_results)
                    if match_results:
                        self.status.setText("")
                    else:
                        self.status.setText("No match found")
            except Exception as err:
                self.status.setText(str(err))
                for matches in self.match_lists:
                    matches.clear()

        self.add_btn.setFocus()

    def _add(self, event):
        count = self.selection.count()
        names = set(self.selection.item(i).text() for i in range(count))

        for i, matches in enumerate(self.match_lists, 1):

            to_add = set(f"{i}: {item.text()}" for item in matches.selectedItems())

            names = names | to_add

        names = natsorted(names)

        self.selection.clear()
        self.selection.addItems(names)

        self.add_btn.setFocus()

    def _apply(self, event):
        count = self.selection.count()

        self.result = set()
        for i in range(count):
            text = self.selection.item(i).text()
            file_index, channel_name = [item.strip() for item in text.split(":")]
            file_index = int(file_index) - 1
            for entry in self.channels_dbs[file_index][channel_name]:
                self.result.add((file_index, entry))
        self.close()

    def _cancel(self, event):
        self.result = set()
        self.close()
