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

"""
Preferences dialog.
"""

# Third party imports
from qtpy.QtCore import Qt, QRegExp, Signal
from qtpy.QtGui import QRegExpValidator, QPixmap
from qtpy.QtWidgets import (QCheckBox, QGridLayout, QHBoxLayout, QLabel,
                            QLineEdit, QPushButton, QVBoxLayout,
                            QWidget)

# Local imports
from anaconda_navigator.api import AnacondaAPI
from anaconda_navigator.config import CONF
from anaconda_navigator.images import WARNING_ICON
from anaconda_navigator.utils.logs import logger
from anaconda_navigator.widgets import ButtonCancel
from anaconda_navigator.widgets.dialogs import DialogBase


class PreferencesDialog(DialogBase):
    sig_urls_updated = Signal(str, str)
    sig_show_application_environments = Signal(bool)

    def __init__(self, *args, **kwargs):
        super(PreferencesDialog, self).__init__(*args, **kwargs)

        self.api = AnacondaAPI()
        self.widgets_changed = set()
        self.widgets = []

        # Widgets
        self.button_ok = QPushButton('Ok')
        self.button_cancel = ButtonCancel('Cancel')
        self.button_reset = QPushButton('Reset to defaults')
        self.row = 0

        # Widget setup
        self.setWindowTitle("Preferences")

        # Layouts
        self.grid_layout = QGridLayout()

        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(self.button_reset)
        buttons_layout.addStretch()
        buttons_layout.addWidget(self.button_ok)
        buttons_layout.addWidget(self.button_cancel)

        main_layout = QVBoxLayout()
        main_layout.addLayout(self.grid_layout)
        main_layout.addSpacing(40)
        main_layout.addLayout(buttons_layout)
        self.setLayout(main_layout)

        # Signals
        self.button_ok.clicked.connect(self.accept)
        self.button_cancel.clicked.connect(self.reject)
        self.button_reset.clicked.connect(self.reset_to_defaults)
        self.button_reset.clicked.connect(
            lambda: self.button_ok.setEnabled(True))

        # Setup
        self.grid_layout.setSpacing(0)
        self.setup()
        self.button_ok.setDisabled(True)
        self.widgets[0].setFocus()
        self.button_ok.setDefault(True)
        self.button_ok.setAutoDefault(True)

    # --- Helpers
    # -------------------------------------------------------------------------
    def get_option(self, option):
        return CONF.get('main', option, None)

    def set_option(self, option, value, default=False):
        CONF.set('main', option, value)

    def set_option_default(self, option):
        default = CONF.get_default('main', option)
        self.set_option(option, default)

    def create_widget(self, widget=None, label=None, option=None, hint=None,
                      check=None):
        if hint:
            widget.setPlaceholderText(hint)

        config_value = self.get_option(option)
        widget.label = QLabel(label)
        widget.option = option
        widget.set_value(config_value)
        widget.label_information = QLabel()
        widget.label_information.setMinimumWidth(20)
        widget.label_information.setMaximumWidth(20)

        form_widget = QWidget()
        h_layout = QHBoxLayout()
        h_layout.addSpacing(4)
        h_layout.addWidget(widget.label_information, 0, Qt.AlignRight)
        h_layout.addWidget(widget, 0, Qt.AlignLeft)
        form_widget.setLayout(h_layout)

        if check:
            widget.check_value = lambda value: check(value)
        else:
            widget.check_value = lambda value: (True, '')

        self.widgets.append(widget)
        self.grid_layout.addWidget(widget.label, self.row, 0,
                                   Qt.AlignRight | Qt.AlignCenter)
        self.grid_layout.addWidget(form_widget, self.row, 1,
                                   Qt.AlignLeft | Qt.AlignCenter)
        self.row += 1

    def create_textbox(self, label, option, hint=None, regex=None,
                       check=None):
        widget = QLineEdit()
        widget.setAttribute(Qt.WA_MacShowFocusRect, False)
        widget.setMinimumWidth(250)

        if regex:
            regex_validator = QRegExpValidator(QRegExp(regex))
            widget.setValidator(regex_validator)

        widget.get_value = lambda w=widget: w.text()
        widget.set_value = lambda value, w=widget: w.setText(value)
        widget.set_warning = lambda w=widget: w.setSelection(0, 1000)
        widget.textChanged.connect(
            lambda v=None, w=widget: self.options_changed(widget=w))

        self.create_widget(widget=widget, option=option, label=label,
                           hint=hint, check=check)

    def create_checkbox(self, label, option, hint=None):
        widget = QCheckBox()
        widget.get_value = lambda w=widget: bool(w.checkState())
        widget.set_value = lambda value, w=widget: bool(
            w.setCheckState(Qt.Checked if value else Qt.Unchecked))
        widget.stateChanged.connect(
            lambda v=None, w=widget: self.options_changed(widget=w))
        self.create_widget(widget=widget, option=option, label=label,
                           hint=hint)

    def options_changed(self, value=None, widget=None):
        config_value = self.get_option(widget.option)

        if config_value != widget.get_value():
            self.widgets_changed.add(widget)
        else:
            if widget in self.widgets_changed:
                self.widgets_changed.remove(widget)

        self.button_ok.setDisabled(not bool(len(self.widgets_changed)))

    # --- API
    # -------------------------------------------------------------------------
    def setup(self):
        self.create_textbox('Anaconda API domain', 'anaconda_api_url',
                            check=self.is_valid_api)
        self.create_textbox('Conda domain', 'conda_url',
                            check=self.is_valid_url)
        self.create_checkbox('Provide analytics', 'provide_analytics')
        self.create_checkbox("Hide quit dialog", 'hide_quit_dialog')

#        self.create_checkbox('Show application<br>environments',
#                             'show_application_environments')

    def warn(self, widget, text=None):
        """
        """
        label = widget.label_information
        if text:
            pixmap = QPixmap(WARNING_ICON)
            label.setPixmap(pixmap.scaled(16, 16, Qt.KeepAspectRatio,
                                          Qt.SmoothTransformation))
            label.setToolTip(str(text))
        else:
            label.setPixmap(QPixmap())
            label.setToolTip('')

    # --- Checkers
    # -------------------------------------------------------------------------
    def is_valid_url(self, url):
        """
        Chek if a given URL returns a 200 code.
        """
        output = self.api.download_is_valid_url(url, non_blocking=False)
        error = ''
        if not output:
            error = 'Invalid url'
        return output, error

    def is_valid_api(self, url):
        """
        Chek if a given URL is a valid anaconda api endpoint.
        """
        output = self.api.download_is_valid_api_url(url, non_blocking=False)
        error = ''
        if not output:
            error = 'Invalid Anaconda API url.'
        return output, error

    def reset_to_defaults(self):
        """
        """
        # ASK!
        for widget in self.widgets:
            option = widget.option
            self.set_option_default(option)
            value = self.get_option(option)
            widget.set_value(value)

    def accept(self):
        """
        Qt override.
        """
        sig_updated = False
        for widget in self.widgets_changed:
            option = widget.option
            value = widget.get_value()
            check, error = widget.check_value(value)

            if check:
                self.set_option(option, value)
                self.warn(widget)
            else:
                self.button_ok.setDisabled(True)
                widget.set_warning()
                self.warn(widget, error)
                return

            if widget.option == 'conda_url':
                sig_updated = True

            if widget.option == 'anaconda_api_url':
                sig_updated = True

            if widget.option == 'show_application_environments':
                self.sig_show_application_environments.emit(value)

        for widget in self.widgets:
            if widget.option == 'anaconda_api_url':
                anaconda_api_url = widget.get_value()
            elif widget.option == 'conda_url':
                conda_url = widget.get_value()

        if sig_updated:
            self.sig_urls_updated.emit(anaconda_api_url, conda_url)

        super(PreferencesDialog, self).accept()


def test():
    from anaconda_navigator.utils.qthelpers import qapplication
    app = qapplication()
    dlg = PreferencesDialog(parent=None)
    dlg.exec_()


if __name__ == '__main__':
    test()
