import os
from Qt import QtCore, QtGui, QtWidgets
from .resources import get_resource
from avalon import style


class ComponentItem(QtWidgets.QFrame):

    signal_remove = QtCore.Signal(object)
    signal_thumbnail = QtCore.Signal(object)
    signal_preview = QtCore.Signal(object)
    signal_repre_change = QtCore.Signal(object, object)

    preview_text = "PREVIEW"
    thumbnail_text = "THUMBNAIL"

    def __init__(self, parent, main_parent):
        super().__init__()
        self.has_valid_repre = True
        self.actions = []
        self.resize(290, 70)
        self.setMinimumSize(QtCore.QSize(0, 70))
        self.parent_list = parent
        self.parent_widget = main_parent
        # Font
        font = QtGui.QFont()
        font.setFamily("DejaVu Sans Condensed")
        font.setPointSize(9)
        font.setBold(True)
        font.setWeight(50)
        font.setKerning(True)

        # Main widgets
        frame = QtWidgets.QFrame(self)
        frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        frame.setFrameShadow(QtWidgets.QFrame.Raised)

        layout_main = QtWidgets.QHBoxLayout(frame)
        layout_main.setSpacing(2)
        layout_main.setContentsMargins(2, 2, 2, 2)

        # Image + Info
        frame_image_info = QtWidgets.QFrame(frame)

        # Layout image info
        layout = QtWidgets.QVBoxLayout(frame_image_info)
        layout.setSpacing(2)
        layout.setContentsMargins(2, 2, 2, 2)

        self.icon = QtWidgets.QLabel(frame)
        self.icon.setMinimumSize(QtCore.QSize(22, 22))
        self.icon.setMaximumSize(QtCore.QSize(22, 22))
        self.icon.setText("")
        self.icon.setScaledContents(True)

        self.btn_action_menu = PngButton(
            name="menu", size=QtCore.QSize(22, 22)
        )

        self.action_menu = QtWidgets.QMenu()

        expanding_sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding
        )
        expanding_sizePolicy.setHorizontalStretch(0)
        expanding_sizePolicy.setVerticalStretch(0)

        layout.addWidget(self.icon, alignment=QtCore.Qt.AlignCenter)
        layout.addWidget(self.btn_action_menu, alignment=QtCore.Qt.AlignCenter)

        layout_main.addWidget(frame_image_info)

        # Name + representation
        self.name = QtWidgets.QLabel(frame)
        self.file_info = QtWidgets.QLabel(frame)
        self.ext = QtWidgets.QLabel(frame)

        self.name.setFont(font)
        self.file_info.setFont(font)
        self.ext.setFont(font)

        self.file_info.setStyleSheet('padding-left:3px;')

        expanding_sizePolicy.setHeightForWidth(
            self.name.sizePolicy().hasHeightForWidth()
        )

        frame_name_repre = QtWidgets.QFrame(frame)

        self.file_info.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.ext.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)
        self.name.setTextInteractionFlags(QtCore.Qt.NoTextInteraction)

        layout = QtWidgets.QHBoxLayout(frame_name_repre)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.name, alignment=QtCore.Qt.AlignLeft)
        layout.addWidget(self.file_info, alignment=QtCore.Qt.AlignLeft)
        layout.addWidget(self.ext, alignment=QtCore.Qt.AlignRight)

        frame_name_repre.setSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.MinimumExpanding
        )

        # Repre + icons
        frame_repre_icons = QtWidgets.QFrame(frame)

        frame_repre = QtWidgets.QFrame(frame_repre_icons)

        label_repre = QtWidgets.QLabel()
        label_repre.setText('Representation:')

        self.input_repre = QtWidgets.QLineEdit()
        self.input_repre.setMaximumWidth(50)

        layout = QtWidgets.QHBoxLayout(frame_repre)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        layout.addWidget(label_repre, alignment=QtCore.Qt.AlignLeft)
        layout.addWidget(self.input_repre, alignment=QtCore.Qt.AlignLeft)

        frame_icons = QtWidgets.QFrame(frame_repre_icons)

        self.preview = LightingButton(self.preview_text)
        self.thumbnail = LightingButton(self.thumbnail_text)

        layout = QtWidgets.QHBoxLayout(frame_icons)
        layout.setSpacing(6)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.thumbnail)
        layout.addWidget(self.preview)

        layout = QtWidgets.QHBoxLayout(frame_repre_icons)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)

        layout.addWidget(frame_repre, alignment=QtCore.Qt.AlignLeft)
        layout.addWidget(frame_icons, alignment=QtCore.Qt.AlignRight)

        frame_middle = QtWidgets.QFrame(frame)

        layout = QtWidgets.QVBoxLayout(frame_middle)
        layout.setSpacing(0)
        layout.setContentsMargins(4, 0, 4, 0)
        layout.addWidget(frame_name_repre)
        layout.addWidget(frame_repre_icons)

        layout.setStretchFactor(frame_name_repre, 1)
        layout.setStretchFactor(frame_repre_icons, 1)

        layout_main.addWidget(frame_middle)

        self.remove = PngButton(name="trash", size=QtCore.QSize(22, 22))
        layout_main.addWidget(self.remove)

        layout = QtWidgets.QVBoxLayout(self)
        layout.setSpacing(0)
        layout.setContentsMargins(2, 2, 2, 2)
        layout.addWidget(frame)

        self.preview.setToolTip('Mark component as Preview')
        self.thumbnail.setToolTip('Component will be selected as thumbnail')

        # self.frame.setStyleSheet("border: 1px solid black;")

    def set_context(self, data):
        self.btn_action_menu.setVisible(False)
        self.in_data = data
        self.remove.clicked.connect(self._remove)
        self.thumbnail.clicked.connect(self._thumbnail_clicked)
        self.preview.clicked.connect(self._preview_clicked)
        self.input_repre.textChanged.connect(self._handle_duplicate_repre)
        name = data['name']
        representation = data['representation']
        ext = data['ext']
        file_info = data['file_info']
        thumb = data['thumb']
        prev = data['prev']
        icon = data['icon']

        resource = None
        if icon is not None:
            resource = get_resource('{}.png'.format(icon))

        if resource is None or not os.path.isfile(resource):
            if data['is_sequence']:
                resource = get_resource('files.png')
            else:
                resource = get_resource('file.png')

        pixmap = QtGui.QPixmap(resource)
        self.icon.setPixmap(pixmap)

        self.name.setText(name)
        self.input_repre.setText(representation)
        self.ext.setText('( {} )'.format(ext))
        if file_info is None:
            self.file_info.setVisible(False)
        else:
            self.file_info.setText('[{}]'.format(file_info))

        self.thumbnail.setVisible(thumb)
        self.preview.setVisible(prev)

    def add_action(self, action_name):
        if action_name.lower() == 'split':
            for action in self.actions:
                if action.text() == 'Split to frames':
                    return
            new_action = QtWidgets.QAction('Split to frames', self)
            new_action.triggered.connect(self.split_sequence)
        elif action_name.lower() == 'merge':
            for action in self.actions:
                if action.text() == 'Merge components':
                    return
            new_action = QtWidgets.QAction('Merge components', self)
            new_action.triggered.connect(self.merge_sequence)
        else:
            print('unknown action')
            return
        self.action_menu.addAction(new_action)
        self.actions.append(new_action)
        if not self.btn_action_menu.isVisible():
            self.btn_action_menu.setVisible(True)
            self.btn_action_menu.clicked.connect(self.show_actions)
            self.action_menu.setStyleSheet(style.load_stylesheet())

    def set_repre_name_valid(self, valid):
        self.has_valid_repre = valid
        if valid:
            self.input_repre.setStyleSheet("")
        else:
            self.input_repre.setStyleSheet("border: 1px solid red;")

    def split_sequence(self):
        self.parent_widget.split_items(self)

    def merge_sequence(self):
        self.parent_widget.merge_items(self)

    def show_actions(self):
        position = QtGui.QCursor().pos()
        self.action_menu.popup(position)

    def _remove(self):
        self.signal_remove.emit(self)

    def _thumbnail_clicked(self):
        self.signal_thumbnail.emit(self)

    def _preview_clicked(self):
        self.signal_preview.emit(self)

    def _handle_duplicate_repre(self, repre_name):
        self.signal_repre_change.emit(self, repre_name)

    def is_thumbnail(self):
        return self.thumbnail.isChecked()

    def change_thumbnail(self, hover=True):
        self.thumbnail.setChecked(hover)

    def is_preview(self):
        return self.preview.isChecked()

    def change_preview(self, hover=True):
        self.preview.setChecked(hover)

    def collect_data(self):
        in_files = self.in_data['files']
        staging_dir = os.path.dirname(in_files[0])

        files = [os.path.basename(file) for file in in_files]
        if len(files) == 1:
            files = files[0]

        data = {
            'ext': self.in_data['ext'],
            'label': self.name.text(),
            'name': self.input_repre.text(),
            'stagingDir': staging_dir,
            'files': files,
            'thumbnail': self.is_thumbnail(),
            'preview': self.is_preview()
        }

        if ("frameStart" in self.in_data and "frameEnd" in self.in_data):
            data["frameStart"] = self.in_data["frameStart"]
            data["frameEnd"] = self.in_data["frameEnd"]

        if 'fps' in self.in_data:
            data['fps'] = self.in_data['fps']

        return data


class LightingButton(QtWidgets.QPushButton):
    lightingbtnstyle = """
    QPushButton {
        font: %(font_size_pt)spt;
        text-align: center;
        color: #777777;
        background-color: transparent;
        border-width: 1px;
        border-color: #777777;
        border-style: solid;
        padding-top: 0px;
        padding-bottom: 0px;
        padding-left: 3px;
        padding-right: 3px;
        border-radius: 3px;
    }

    QPushButton:hover {
        border-color: #cccccc;
        color: #cccccc;
    }

    QPushButton:pressed {
        border-color: #ffffff;
        color: #ffffff;
    }

    QPushButton:disabled {
        border-color: #3A3939;
        color: #3A3939;
    }

    QPushButton:checked {
        border-color: #4BB543;
        color: #4BB543;
    }

    QPushButton:checked:hover {
        border-color: #4Bd543;
        color: #4Bd543;
    }

    QPushButton:checked:pressed {
        border-color: #4BF543;
        color: #4BF543;
    }
    """

    def __init__(self, text, font_size_pt=8, *args, **kwargs):
        super(LightingButton, self).__init__(text, *args, **kwargs)
        self.setStyleSheet(self.lightingbtnstyle % {
            "font_size_pt": font_size_pt
        })
        self.setCheckable(True)


class PngFactory:
    png_names = None

    @classmethod
    def init(cls):
        cls.png_names = {
            "trash": {
                "normal": QtGui.QIcon(get_resource("trash.png")),
                "hover": QtGui.QIcon(get_resource("trash_hover.png")),
                "pressed": QtGui.QIcon(get_resource("trash_pressed.png")),
                "pressed_hover": QtGui.QIcon(
                    get_resource("trash_pressed_hover.png")
                ),
                "disabled": QtGui.QIcon(get_resource("trash_disabled.png"))
            },

            "menu": {
                "normal": QtGui.QIcon(get_resource("menu.png")),
                "hover": QtGui.QIcon(get_resource("menu_hover.png")),
                "pressed": QtGui.QIcon(get_resource("menu_pressed.png")),
                "pressed_hover": QtGui.QIcon(
                    get_resource("menu_pressed_hover.png")
                ),
                "disabled": QtGui.QIcon(get_resource("menu_disabled.png"))
            }
        }

    @classmethod
    def get_png(cls, name):
        if cls.png_names is None:
            cls.init()
        return cls.png_names.get(name)


class PngButton(QtWidgets.QPushButton):
    png_button_style = """
    QPushButton {
        border: none;
        background-color: transparent;
        padding-top: 0px;
        padding-bottom: 0px;
        padding-left: 0px;
        padding-right: 0px;
    }
    QPushButton:hover {}
    QPushButton:pressed {}
    QPushButton:disabled {}
    QPushButton:checked {}
    QPushButton:checked:hover {}
    QPushButton:checked:pressed {}
    """

    def __init__(
        self, name=None, path=None, hover_path=None, pressed_path=None,
        hover_pressed_path=None, disabled_path=None,
        size=None, *args, **kwargs
    ):
        self._hovered = False
        self._pressed = False
        super(PngButton, self).__init__(*args, **kwargs)
        self.setStyleSheet(self.png_button_style)

        png_dict = {}
        if name:
            png_dict = PngFactory.get_png(name) or {}
            if not png_dict:
                print((
                    "WARNING: There is not set icon with name \"{}\""
                    "in PngFactory!"
                ).format(name))

        ico_normal = png_dict.get("normal")
        ico_hover = png_dict.get("hover")
        ico_pressed = png_dict.get("pressed")
        ico_hover_pressed = png_dict.get("pressed_hover")
        ico_disabled = png_dict.get("disabled")

        if path:
            ico_normal = QtGui.QIcon(path)
        if hover_path:
            ico_hover = QtGui.QIcon(hover_path)

        if pressed_path:
            ico_pressed = QtGui.QIcon(hover_path)

        if hover_pressed_path:
            ico_hover_pressed = QtGui.QIcon(hover_pressed_path)

        if disabled_path:
            ico_disabled = QtGui.QIcon(disabled_path)

        self.setIcon(ico_normal)
        if size:
            self.setIconSize(size)
            self.setMaximumSize(size)

        self.ico_normal = ico_normal
        self.ico_hover = ico_hover
        self.ico_pressed = ico_pressed
        self.ico_hover_pressed = ico_hover_pressed
        self.ico_disabled = ico_disabled

    def setDisabled(self, in_bool):
        super(PngButton, self).setDisabled(in_bool)
        icon = self.ico_normal
        if in_bool and self.ico_disabled:
            icon = self.ico_disabled
        self.setIcon(icon)

    def enterEvent(self, event):
        self._hovered = True
        if not self.isEnabled():
            return
        icon = self.ico_normal
        if self.ico_hover:
            icon = self.ico_hover

        if self._pressed and self.ico_hover_pressed:
            icon = self.ico_hover_pressed

        if self.icon() != icon:
            self.setIcon(icon)

    def mouseMoveEvent(self, event):
        super(PngButton, self).mouseMoveEvent(event)
        if self._pressed:
            mouse_pos = event.pos()
            hovering = self.rect().contains(mouse_pos)
            if hovering and not self._hovered:
                self.enterEvent(event)
            elif not hovering and self._hovered:
                self.leaveEvent(event)

    def leaveEvent(self, event):
        self._hovered = False
        if not self.isEnabled():
            return
        icon = self.ico_normal
        if self._pressed and self.ico_pressed:
            icon = self.ico_pressed

        if self.icon() != icon:
            self.setIcon(icon)

    def mousePressEvent(self, event):
        self._pressed = True
        if not self.isEnabled():
            return
        icon = self.ico_hover
        if self.ico_pressed:
            icon = self.ico_pressed

        if self.ico_hover_pressed:
            mouse_pos = event.pos()
            if self.rect().contains(mouse_pos):
                icon = self.ico_hover_pressed

        if icon is None:
            icon = self.ico_normal

        if self.icon() != icon:
            self.setIcon(icon)

    def mouseReleaseEvent(self, event):
        if not self.isEnabled():
            return
        if self._pressed:
            self._pressed = False
            mouse_pos = event.pos()
            if self.rect().contains(mouse_pos):
                self.clicked.emit()

        icon = self.ico_normal
        if self._hovered and self.ico_hover:
            icon = self.ico_hover

        if self.icon() != icon:
            self.setIcon(icon)
