from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import QTableWidgetItem

from core.repositories import TrackRepository, SessionTrackRepository
from ui.qt.widgets.sqt.SQTableWidget import SQTableWidget


class PlaylistTable(SQTableWidget):
    trackSelected = pyqtSignal(object)
    trackDoubleClicked = pyqtSignal(object)

    def __init__(self, parent):
        super().__init__(parent)
        self.playlist = None
        self.count = -1
        self.cellPressed.connect(self._cellPressed)
        self.cellDoubleClicked.connect(self._cellDoubleClicked)

    def populate(self, playlist=None):
        if playlist:
            self.playlist = playlist
        if not self.playlist:
            return

        self.hideColumn(0)
        self.hideColumn(1)
        header = self.horizontalHeader()
        header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
        self.setColumnWidth(3, 50)
        self.hideColumn(4)

        self.clear()
        self.update()

    def update(self):
        if not self.playlist:
            raise RuntimeError("No playlist loaded")

        self.setUpdatesEnabled(False)

        session_track_repo = SessionTrackRepository()
        track_repo = TrackRepository()

        session_tracks = session_track_repo.get_by_session_id(self.playlist.id)
        if not session_tracks:
            self.clear()
            self.setUpdatesEnabled(True)
            return

        loaded = {self.item(row, 0).data(0): row for row in self.rows()}
        for session_track_id, row in loaded.items():
            if session_track_id not in [st.id for st in session_tracks]:
                self.removeRow(row)

        i = 0
        for session_track in session_tracks:
            track = track_repo.get_by_id(session_track.track_id)

            if session_track.id in loaded:
                row = loaded[session_track.id]
            else:
                row = self.rowCount()
                self.insertRow(row)

                item = QTableWidgetItem()
                item.setData(0, session_track.id)
                self.setItem(i, 0, item)

            item = QTableWidgetItem()
            item.setData(0, track.id)
            self.setItem(row, 1, item)

            self.setItem(row, 2, QTableWidgetItem(track.title))

            item = QTableWidgetItem(track.literal_duration())
            item.setTextAlignment(Qt.AlignCenter)
            self.setItem(row, 3, item)

            item = QTableWidgetItem()
            item.setData(0, session_track.order)
            self.setItem(row, 4, item)

            i += 1
        self.count = i

        self.sortItems(4)

        self.setUpdatesEnabled(True)

    def clear(self):
        while self.rowCount():
            self.removeRow(0)
        super().clear()

    def _cellPressed(self, row, _):
        track_id = int(self.item(row, 1).data(0))
        if track_id:
            track = TrackRepository().get_by_id(track_id)
            self.trackSelected.emit(track)

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

    def selected_session_track(self):
        item = self.item(self.currentRow(), 0)
        if not item:
            return None
        session_track_id = item.data(0)
        if not session_track_id:
            return None
        return SessionTrackRepository().get_by_id(int(session_track_id))

    def set_is_playing(self, track=None):
        for i in self.rows():
            track_id = self.item(i, 1).data(0)

            if track is not None and track_id == track.id:
                icon = QIcon(":/img/rsc/play.png")
            else:
                icon = QIcon()
            self.item(i, 2).setIcon(icon)

    def update_session_track_order(self, session_track, new_order):
        session_track_repo = SessionTrackRepository()
        session_track_repo.set_session_track_order(session_track, new_order, True)
        self.update()

    def move_selected_up(self, track):
        session_track = self.selected_session_track()
        if session_track:
            self.update_session_track_order(session_track, session_track.order - 1)

    def move_selected_down(self, track):
        session_track = self.selected_session_track()
        if session_track:
            self.update_session_track_order(session_track, session_track.order + 1)

    def move_selected_to_top(self, track):
        session_track = self.selected_session_track()
        if session_track:
            self.update_session_track_order(session_track, 0)

    def move_selected_to_bottom(self, track):
        session_track = self.selected_session_track()
        if session_track:
            self.update_session_track_order(session_track, 99999999)
