from pathlib import Path
from qgis.PyQt.QtCore import QSize, Qt, QSortFilterProxyModel
from qgis.PyQt.QtWidgets import QStyle, QComboBox, QStyleOptionComboBox, QStylePainter, QCompleter, QAbstractItemView, QStyledItemDelegate, QListView
from qgis.PyQt.QtGui import QStandardItemModel, QStandardItem, QPaintEvent
from SAGisXPlanung import BASE_DIR
from SAGisXPlanung.gui.style import RemoveFrameFocusProxyStyle, FixComboStyleDelegate

class MultiSelectComboBox(QComboBox):

    def __init__(self, empty_text='Auswählen...', parent=None):
        super(MultiSelectComboBox, self).__init__(parent)
        self.setModel(QStandardItemModel(self))
        self.model().itemChanged.connect(self.on_item_changed)
        self.view().pressed.connect(self.on_item_pressed)
        self.setEditable(False)
        self.setItemDelegate(FixComboStyleDelegate())
        self.setStyleSheet('QListView::item { padding: 5px }')
        self._proxy_style = RemoveFrameFocusProxyStyle('Fusion')
        self._proxy_style.setParent(self)
        self.setStyle(self._proxy_style)
        self.empty_text = empty_text
        self.display_text = self.empty_text

    def add_item(self, text, data=None, check_state=Qt.CheckState.Unchecked):
        item = QStandardItem(text)
        item.setFlags(Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsEnabled)
        item.setData(data, Qt.ItemDataRole.UserRole)
        self.model().appendRow(item)
        item.setCheckState(check_state)

    def on_item_pressed(self, index):
        item = self.model().itemFromIndex(index)
        if item.checkState() == Qt.CheckState.Checked:
            item.setCheckState(Qt.CheckState.Unchecked)
        else:
            item.setCheckState(Qt.CheckState.Checked)

    def on_item_changed(self, item: QStandardItem):
        self.update_display_text()

    def checked_items(self, role=Qt.ItemDataRole.DisplayRole):
        checked_items = []
        for i in range(self.model().rowCount()):
            item = self.model().item(i)
            if item.checkState() == Qt.CheckState.Checked:
                checked_items.append(item.data(role))
        return checked_items

    def update_display_text(self):
        checked_items = self.checked_items()
        self.display_text = ', '.join(checked_items) if checked_items else self.empty_text

    def paintEvent(self, event: QPaintEvent=None):
        opt = QStyleOptionComboBox()
        self.initStyleOption(opt)
        p = QStylePainter(self)
        p.drawComplexControl(QStyle.ComplexControl.CC_ComboBox, opt)
        text_rect = self.style().subControlRect(QStyle.ComplexControl.CC_ComboBox, opt, QStyle.SubControl.SC_ComboBoxEditField)
        opt.currentText = p.fontMetrics().elidedText(self.display_text, Qt.TextElideMode.ElideRight, text_rect.width())
        p.drawControl(QStyle.ControlElement.CE_ComboBoxLabel, opt)

    def sizeHint(self):
        hint = super().sizeHint()
        return QSize(min(100, hint.width()), hint.height())

class SearchableComboBox(QComboBox):

    def __init__(self, parent=None):
        super(SearchableComboBox, self).__init__(parent)
        self.setFocusPolicy(Qt.FocusPolicy.ClickFocus)
        self.setEditable(True)
        self.setInsertPolicy(QComboBox.InsertPolicy.NoInsert)
        self.filter_model = QSortFilterProxyModel(self)
        self.filter_model.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
        self.filter_model.setSourceModel(self.model())
        self.completer = QCompleter(self.filter_model, self)
        self.completer.setCompletionMode(QCompleter.CompletionMode.UnfilteredPopupCompletion)
        self.setCompleter(self.completer)
        icon_path = Path(BASE_DIR, 'gui', 'resources', 'arrow_drop_down.svg').as_posix()
        self.setStyleSheet(f'\n            QComboBox::drop-down {{\n                subcontrol-origin: padding;\n                subcontrol-position: top right;\n                width: 30px;      \n                border: none;        \n                background: transparent;\n            }}\n            QComboBox::down-arrow {{\n                image: url({icon_path});\n                width: 24px; \n                height: 24px;\n            }}\n        ')
        view_sheet_style = '      \n            QAbstractItemView { \n                background-color: white;\n                selection-background-color: #d1d5db;\n                selection-color: black;\n            }    \n            QAbstractItemView::item { \n                border: none;\n                padding: 5px; \n            }\n            \n            QAbstractItemView QScrollBar:vertical {\n                background: #f9fafb;\n                width: 8px;\n                border-radius: 4px;\n                margin: 2px;\n            }\n            \n            QAbstractItemView QScrollBar::handle:vertical {\n                background: #d1d5db;\n                border-radius: 4px;\n                min-height: 20px;\n            }\n            \n            QAbstractItemView QScrollBar::handle:vertical:hover {\n                background: #9ca3af;\n            }\n            \n            QAbstractItemView QScrollBar::add-line:vertical,\n            QAbstractItemView QScrollBar::sub-line:vertical {\n                height: 0px;\n            }\n        '
        self.view().setStyleSheet(view_sheet_style)
        self._proxy_style = RemoveFrameFocusProxyStyle('Fusion')
        self._proxy_style.setParent(self)
        self.view().setStyle(self._proxy_style)
        self.completer_view = QListView(self)
        self.completer_view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        self.completer_view.setMouseTracking(True)
        self.completer_view.setStyleSheet(view_sheet_style)
        self.completer_view.setStyle(self._proxy_style)
        self.completer.setPopup(self.completer_view)
        self.completer.popup().setItemDelegate(QStyledItemDelegate())
        self.setItemDelegate(QStyledItemDelegate())
        self.lineEdit().textEdited[str].connect(self.filter_model.setFilterFixedString)
        self.completer.activated.connect(self.on_completer_activated)

    def on_completer_activated(self, text):
        if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
            self.activated[str].emit(self.itemText(index))

    def setModel(self, model):
        super(SearchableComboBox, self).setModel(model)
        self.filter_model.setSourceModel(model)
        self.completer.setModel(self.filter_model)

    def setModelColumn(self, column):
        self.completer.setCompletionColumn(column)
        self.filter_model.setFilterKeyColumn(column)
        super(SearchableComboBox, self).setModelColumn(column)