# -*- coding: utf-8 -*-
#
# Copyright 2016 Continuum Analytics, Inc.
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
#

"""
Widgets to list environemnts available to edit in the Environments tab.
"""

from __future__ import absolute_import, division, print_function

# Third party imports
from qtpy.QtCore import QSize, Qt, Signal, QTimer
from qtpy.QtGui import QMovie
from qtpy.QtWidgets import (QAbstractItemView, QHBoxLayout, QFrame, QLabel,
                            QListWidget, QListWidgetItem, QPushButton,
                            QWidget,
                            )

# Local imports
from anaconda_navigator.images import SPINNER_GREEN_16_PATH
from anaconda_navigator.widgets import WidgetBase, ButtonEnvironmentOptions
from anaconda_navigator.utils.qthelpers import qapplication
from anaconda_navigator.utils.styles import load_style_sheet
from anaconda_navigator.utils.logs import logger


class ListWidgetEnvironment(QListWidget):
    sig_item_selected = Signal(object)

    def __init__(self, *args, **kwargs):
        super(ListWidgetEnvironment, self).__init__(*args, **kwargs)
        self._items = []

        # Widget setup
        self.setFrameStyle(QFrame.Plain)
        self.setFocusPolicy(Qt.NoFocus)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setMovement(QListWidget.Static)
        self.setResizeMode(QListWidget.Adjust)
        self.setSelectionMode(QAbstractItemView.NoSelection)
        self.setViewMode(QListWidget.IconMode)
        self.update_style_sheet()
        self.setFocusPolicy(Qt.NoFocus)
        self._current_item = None
        self.timer = QTimer()
        self.timer.timeout.connect(self.repaint)
        self.timer.start(300)

    def update_style_sheet(self, style_sheet=None):
        if style_sheet is None:
            style_sheet = load_style_sheet()
        self.setStyleSheet(style_sheet)

    def addItem(self, item):
        """
        Add an item to the list.
        """
        if isinstance(item, ListItemSeparator):
            QListWidget.addItem(self, item)
            self.setItemWidget(item, item.widget)
        else:
            self._items.append(item)
            QListWidget.addItem(self, item)
            self.setItemWidget(item, item.widget)
            index = self._items.index(item)

            item.widget.clicked.connect(
                lambda v=None, i=index: self.setCurrentRow(i))
            item.widget.clicked.connect(
                lambda v=None, it=item: self.sig_item_selected.emit(it))
            item.widget.sig_entered.connect(
                lambda v=None: item.set_hovered(True))
            item.widget.sig_left.connect(
                lambda v=None: item.set_hovered(False))
            item.button_name.clicked.connect(
                lambda v=None, it=item: self.sig_item_selected.emit(it))
            item.button_name.clicked.connect(
                lambda v=None, i=index: self.setCurrentRow(i))
            item.button_name.sig_entered.connect(
                lambda v=None: item.set_hovered(True))
            item.button_name.sig_left.connect(
                lambda v=None: item.set_hovered(False))

            if self._current_item is None:
                self._current_item = item
                self.setCurrentRow(0)
            else:
                item.set_selected(False)

    def clear(self):
        super(ListWidgetEnvironment, self).clear()
        self._items = []

    def count(self):
        return len(self._items)

    def setCurrentRow(self, row):
        for i, item in enumerate(self._items):
            if i == row:
                item.set_selected(True)
                item.set_loading(True)
                self._current_item = item
            else:
                item.set_selected(False)
                item.set_loading(False)

    def currentItem(self):
        return self._current_item

    def currentIndex(self):
        if self._current_item in self._items:
            return self._items.index(self._current_item)
        else:
            return None

    def item(self, index):
        return self._items[index]


class WidgetSeparator(QWidget):
    pass


class WidgetEnvironment(WidgetBase):
    sig_entered = Signal()
    sig_left = Signal()
    clicked = Signal()

    def __init__(self, *args, **kwargs):
        super(WidgetEnvironment, self).__init__(*args, **kwargs)
        self._hover = False
        self.setFocusPolicy(Qt.NoFocus)

    def enterEvent(self, event):
        super(WidgetEnvironment, self).enterEvent(event)
        self._hover = True
        self.sig_entered.emit()

    def leaveEvent(self, event):
        super(WidgetEnvironment, self).enterEvent(event)
        self._hover = False
        self.sig_left.emit()

    def mouseReleaseEvent(self, event):
        super(WidgetEnvironment, self).enterEvent(event)
        if self._hover:
            self.clicked.emit()


class ButtonEnvironmentName(QPushButton):
    sig_entered = Signal()
    sig_left = Signal()

    def focusInEvent(self, event):
        super(ButtonEnvironmentName, self).focusInEvent(event)
        self.sig_entered.emit()

    def focusOutEvent(self, event):
        super(ButtonEnvironmentName, self).focusOutEvent(event)
        self.sig_left.emit()

    def enterEvent(self, event):
        super(ButtonEnvironmentName, self).enterEvent(event)
        self.sig_entered.emit()

    def leaveEvent(self, event):
        super(ButtonEnvironmentName, self).enterEvent(event)
        self.sig_left.emit()

    def setProperty(self, name, value):
        QPushButton.setProperty(self, name, value)
        self.style().unpolish(self)
        self.style().polish(self)
        self.update()

    def set_selected(self, value):
        self._selected = value
        self.setProperty('_selected', value)

    def set_hovered(self, value):
        self.setProperty('_hovered', value)


class LabelEnvironmentIcon(QLabel):
    pass


class ListItemEmpty(QListWidgetItem):
    pass


class ListItemSeparator(QListWidgetItem):
    def __init__(self, text=''):
        super(ListItemSeparator, self).__init__()

        self.widget = WidgetSeparator()
        self.widget.setStyleSheet(load_style_sheet())
        self.label = QLabel(text)

        layout = QHBoxLayout()
        layout.addWidget(self.label)

        self.widget.setLayout(layout)
        self.setSizeHint(self.widget.sizeHint())

    def sizeHint(self):
        return QSize(10, 10)


class ListItemEnvironment(QListWidgetItem):
    """
    Widget to build an item for the environments list.
    """
    def __init__(self, name=None, prefix=None):
        super(ListItemEnvironment, self).__init__()

        self._selected = False
        self._name = name
        self._prefix = prefix

        # Widgets
        self.button_options = ButtonEnvironmentOptions()
        self.button_name = ButtonEnvironmentName(name)
        self.label_icon = LabelEnvironmentIcon()
        self.movie = QMovie(SPINNER_GREEN_16_PATH)
        self.widget = WidgetEnvironment()
        self.widget.setFocusPolicy(Qt.NoFocus)
        self.widget.button_name = self.button_name
        self.widget.button_options = self.button_options

        # Widget setup
        self.label_icon.setMovie(self.movie)
        self.button_name.setDefault(True)

        # Layouts
        layout = QHBoxLayout()
        layout.addWidget(self.label_icon)
        layout.addWidget(self.button_name)
        layout.addWidget(self.button_options)
        layout.addStretch()

        self.widget.setLayout(layout)
        self.widget.setStyleSheet(load_style_sheet())
        self.setSizeHint(self.widget.sizeHint())

    def text(self):
        return self._name

    def prefix(self):
        return self._prefix

    def set_hovered(self, value):
        self.widget.setProperty('_hovered', value)
        self.button_name.set_hovered(value)

    def set_loading(self, value):
        # self.button_options.setDisabled(value)
        if value:
            self.label_icon.setMovie(self.movie)
            self.movie.start()
        else:
            self.label_icon.setMovie(QMovie())
            self.button_options.setFocus()

    def set_selected(self, value):
        self._selected = value
        try:
            self.widget.setProperty('_selected', value)
            self.button_name.set_selected(value)
        except RuntimeError:
            pass

        self.button_name.setDisabled(value)

        if value:
            self.label_icon.setMovie(None)
            self.button_name.setFocusPolicy(Qt.NoFocus)
            self.button_options.setVisible(True)
            self.button_options.setFocus()
        else:
            self.label_icon.setMovie(None)
            self.button_name.setFocusPolicy(Qt.TabFocus)
            self.button_options.setVisible(False)


def print_selected(item):
    print('Item selected: ', item.text())


def test():
    app = qapplication()
    w = ListWidgetEnvironment()
    w.sig_item_selected.connect(print_selected)
    w.addItem(ListItemEnvironment('root'))

    for i in range(5):
        item = ListItemEnvironment('env ' + str(i))
        w.addItem(item)

    w.addItem(ListItemSeparator('Application environments:'))

    for i in range(3):
        item = ListItemEnvironment('application env ' + str(i))
        w.addItem(item)

    w.show()
    app.exec_()


if __name__ == "__main__":
    test()
