# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2016-2017 Anaconda, Inc.
#
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
# -----------------------------------------------------------------------------
"""Team Edition login dialogs."""

__all__ = ['TeamEditionSetDomainPage', 'TeamEditionLoginPage', 'TeamEditionAddChannelsPage']

import typing

from qtpy.QtCore import Qt
from qtpy.QtGui import QPixmap
from qtpy.QtWidgets import QApplication, QHBoxLayout, QLabel, QVBoxLayout, QWidget
from anaconda_navigator.utils import get_domain_from_api_url
from anaconda_navigator.api.anaconda_api import AnacondaAPI
from anaconda_navigator.api.team_edition_api import SSL_ERROR_MESSAGE
from anaconda_navigator.config import TEAM_EDITION_BRAND, CONF
from anaconda_navigator.utils.analytics import GATracker
from anaconda_navigator.utils import url_utils
from anaconda_navigator.widgets import ButtonPrimary
from anaconda_navigator.widgets.manager.channels import SelectableChannelsListTable
from anaconda_navigator.static.images import ANACONDA_TEAM_EDITION_LOGIN_LOGO
from anaconda_navigator.widgets.dialogs.login import styling
from anaconda_navigator.widgets.dialogs.login.utils import TextContainer
from anaconda_navigator.widgets.dialogs.login.base_dialogs import (
    BasePage, BaseSettingPage, TrustServerDialog, BaseLoginPage,
)


TEAM_SET_DOMAIN_TEXT_CONTAINER = TextContainer(
    form_primary_text=(
        'Looks like this is the first time you are logging into Team Edition. Please set your Team Edition domain.'
    ),
    form_secondary_text='You only need to set this domain once. You can always change this in your Preferences.',
    form_input_label_text='Team Edition Domain',
    form_submit_button_text='Set Domain',
    info_frame_logo_path=ANACONDA_TEAM_EDITION_LOGIN_LOGO,
    info_frame_text='Login to configure Conda and Navigator to install packages from your Team Edition instance.',
)

TEAM_LOGIN_TEXT_CONTAINER = TextContainer(
    info_frame_logo_path=ANACONDA_TEAM_EDITION_LOGIN_LOGO,
    info_frame_text='Login to configure Conda and Navigator to install packages from your Team Edition instance.',
    message_box_error_text='The Team Edition API domain is not specified! Please, set in preferences.',
)


class TeamEditionSetDomainPage(BaseSettingPage):

    def __init__(self, parent: typing.Optional[QWidget] = None) -> None:
        super().__init__(AnacondaAPI(), TEAM_SET_DOMAIN_TEXT_CONTAINER, parent=parent)
        self.api_url_config_option = 'team_edition_api_url'
        self.input_line.setPlaceholderText('http(s)://example.com')
        self.button_apply.clicked.connect(self.set_domain)

    def check_text(self) -> bool:
        text: str = self.input_line.text()
        domain: str = get_domain_from_api_url(text)

        self.input_line.setText(url_utils.join(domain, 'api/system'))
        if super().check_text():
            self.input_line.setText(domain)
            return True

        self.input_line.setText(text)
        return False


class TeamEditionLoginPage(BaseLoginPage):

    def __init__(self, parent: typing.Optional[QWidget] = None) -> None:
        super().__init__(AnacondaAPI(), TEAM_LOGIN_TEXT_CONTAINER, parent=parent)
        self.api_url_config_option = 'team_edition_api_url'
        self.brand = TEAM_EDITION_BRAND

    def _finished(self, worker, token, error):
        """
        Callback for the login procedure after worker has finished.

        If success, sets the token, 'username' attribute to parent widget
        and sends the accept signal.

        Otherwise, outputs error messages.
        """
        if token:
            self.accept()
            self.create_login_data()

        elif error:
            self.label_message.setText(f"<i>{error}</i>")
            self.label_message.setVisible(True)
            self._track_error(error)

            if error == SSL_ERROR_MESSAGE:
                if TrustServerDialog(url=CONF.get('main', self.api_url_config_option), parent=self).exec_():
                    self.login()
                    return

            CONF.set('main', 'logged_api_url', None)
            CONF.set('main', 'logged_brand', None)
            self.api.client_reload()

        self.button_login.setDisabled(False)
        self.check_text()
        QApplication.restoreOverrideCursor()

    def _track_error(self, error):
        domain = self.api.client_domain()
        label = '{0}/{1}: {2}'.format(domain, self.username, str(error).lower())
        self.tracker.track_event('authenticate', 'login failed', label=label)
        self.text_password.setFocus()
        self.text_password.selectAll()

    def create_login_data(self):
        self.api.create_login_data()


class TeamEditionAddChannelsPage(BasePage):

    def __init__(
            self,
            msg: str = 'Select channels to be used',
            btn_add_msg: str = 'Add Channels',
            btn_cancel_msg: str = 'Skip',
            parent: typing.Optional[QWidget] = None,
    ) -> None:
        super().__init__(parent)

        self.api = AnacondaAPI()
        self.tracker = GATracker()

        QApplication.restoreOverrideCursor()
        pixmap = QPixmap(ANACONDA_TEAM_EDITION_LOGIN_LOGO)
        pixmap = pixmap.scaledToWidth(200, Qt.SmoothTransformation)
        label_icon = styling.LabelLoginLogo()
        label_icon.setPixmap(pixmap)
        label_icon.setAlignment(Qt.AlignLeft)
        self.label_information = QLabel(msg)

        rc_data = self.api._conda_api.load_rc() or dict()
        api_channels_data = self.api.get_channels()
        channels = rc_data.get('channels', [])
        default_channels = rc_data.get('default_channels', [])

        self.channels_table = SelectableChannelsListTable(
            self, table_data=api_channels_data, channels=channels, default_channels=default_channels
        )
        self.channels_table.setMaximumWidth(650)

        self.button_skip = styling.SecondaryButton(btn_cancel_msg)
        self.button_add = ButtonPrimary(btn_add_msg)

        buttons_layout = QHBoxLayout()
        buttons_layout.addWidget(self.button_skip)
        buttons_layout.addWidget(self.button_add)

        self.main_layout = QVBoxLayout()
        self.main_layout.addWidget(label_icon, Qt.AlignLeft)
        self.main_layout.addWidget(self.label_information, Qt.AlignRight)
        self.main_layout.addWidget(self.channels_table, Qt.AlignCenter)
        self.main_layout.addLayout(buttons_layout)

        self.setLayout(self.main_layout)

        self.button_skip.clicked.connect(self.reject)
        self.button_add.clicked.connect(self.add_channels)

    def add_channels(self):
        default_channels, channels = self.channels_table.get_selected_channels()

        if not default_channels:
            self.label_information.setText(
                'At least one channel should be added to <b>default_channels</b>! Please add...',
            )
            return

        self.api.update_channels(default_channels, channels)
        self.accept()
