from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QIcon, QBrush, QColor
from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QTreeWidgetItemIterator

from core import db
from core.logging_ import Logger
from core.repositories import TrackRepository
from core.utils import norm_search

logger = Logger.get()


class ExplorerTable(QTreeWidget):
    trackSelected = pyqtSignal(object)
    trackDoubleClicked = pyqtSignal(object)

    def __init__(self, parent):
        super(QTreeWidget, self).__init__(parent)
        self.setColumnCount(3)
        self.setColumnWidth(0, 54)
        self.hideColumn(2)
        self.itemDoubleClicked.connect(self._itemDoubleClicked)
        self.artist_items, self.album_items, self.track_items = {}, {}, {}

    def populate(self):
        session = db.Session()
        track_repo = TrackRepository(session)
        self.clear()

        self.artist_items, self.album_items, self.track_items = {}, {}, {}

        tracks = track_repo.get_all()

        self.setUpdatesEnabled(False)
        self.update_tracks(tracks)
        self.setUpdatesEnabled(True)
        self.trackSelected.emit(None)

    def update_tracks(self, tracks):

        for track in tracks:
            if track.artist and track.artist not in self.artist_items:
                item = QTreeWidgetItem(self)
                item.setIcon(0, QIcon(":/img/rsc/artist.png"))
                item.setText(1, track.artist)
                self.artist_items[track.artist] = item

        for track in tracks:
            # list albums with artists
            if track.artist and track.album and (track.artist, track.album) not in self.album_items:
                item = QTreeWidgetItem(self.artist_items[track.artist])
                item.setIcon(0, QIcon(":/img/rsc/album.png"))
                item.setText(1, track.album)
                self.album_items[(track.artist, track.album)] = item

        for track in tracks:

            if track.id not in self.track_items:
                if track.artist and track.album:
                    parent = self.album_items[(track.artist, track.album)]
                elif track.artist:
                    parent = self.artist_items[track.artist]
                else:
                    parent = self

                item = QTreeWidgetItem(parent)
                item.setIcon(0, QIcon(":/img/rsc/music.png"))
                item.setData(2, 0, track.id)
                self.track_items[track.id] = item

            if track.status != track.STATUS_UNAVAILABLE:
                title = track.title
                color = QColor(20, 20, 20)
            else:
                title = f"[Introuvable] {track.title}"
                color = QColor(200, 20, 20)

            self.track_items[track.id].setText(1, title)
            self.track_items[track.id].setForeground(0, QBrush(color))
            self.track_items[track.id].setForeground(1, QBrush(color))

    def selected_track(self):
        track_id = self.selectionModel().selection().indexes()[2].data(2)
        if not track_id:
            return None
        return TrackRepository().get_by_id(int(track_id))

    def selectionChanged(self, selected, _):
        try:
            track_id = selected.indexes()[2].data(2)
        except IndexError:
            return
        if track_id:
            track = TrackRepository().get_by_id(int(track_id))
        else:
            track = None
        self.trackSelected.emit(track)

    def _itemDoubleClicked(self, item, _):
        track_id = item.data(2, 0)
        if track_id:
            track = TrackRepository().get_by_id(int(track_id))
            self.trackDoubleClicked.emit(track)

    def filterBy(self, tag_id=None, search_text=""):

        track_ids = []
        if tag_id:
            track_repo = TrackRepository()
            track_ids = [t.id for t in track_repo.get_by_tag_id(tag_id)]

        search_text = norm_search(search_text)

        self.setUpdatesEnabled(False)

        iterator = QTreeWidgetItemIterator(self)
        while True:
            item = iterator.value()
            if item is not None:

                if not item.data(2, 0):
                    # not a track
                    item.setHidden(True)
                    iterator += 1
                    continue

                track_item = item
                parent_item = item.parent()
                grand_parent_item = parent_item.parent() if parent_item else None

                keys = [track_item.text(1)]
                if parent_item:
                    keys.append(parent_item.text(1))
                if grand_parent_item:
                    keys.append(grand_parent_item.text(1))

                s = norm_search(" ".join(keys))
                hide = (search_text and search_text not in s) \
                       or (tag_id and item.data(2, 0) not in track_ids)

                track_item.setHidden(hide)

                iterator += 1
            else:
                break

        iterator = QTreeWidgetItemIterator(self)
        while True:
            item = iterator.value()
            if item is not None:
                if not item.data(2, 0) or item.isHidden():
                    # not a track or hidden
                    iterator += 1
                    continue

                if item.parent():
                    item.parent().setHidden(False)
                if item.parent() and item.parent().parent():
                    item.parent().parent().setHidden(False)

                iterator += 1
            else:
                break

        if search_text or tag_id:
            self.expandAll()
        else:
            self.collapseAll()

        self.setUpdatesEnabled(True)
