# -*- 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 json
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.config import TEAM_EDITION_BRAND
from anaconda_navigator.utils.analytics import GATracker
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 . import styling
from .utils import TextContainer
from .base_dialogs import BasePage, BaseSettingPage, 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):
        text = self.input_line.text()
        domain = get_domain_from_api_url(text)
        self.input_line.setText('{}/api/system'.format(domain))
        is_valid = super(TeamEditionSetDomainPage, self).check_text()
        self.input_line.setText(domain)
        return is_valid


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, output, 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.
        """
        try:
            response = json.loads(output)

            if 'token' in response and 'refresh_token' in response:
                self.token = output
                self.accept()
                te_channels = TeamEditionAddChannelsPage()
                te_channels.open()

            else:
                if 'message' in response and response['message'] == 'Unauthorized':
                    self.label_message.setText('<i>Invalid Credentials!</i>')
                elif 'message' in response:
                    self.label_message.setText('<i>{}</i>'.format(response['message']))

                self.label_message.setVisible(True)
                self._track_error(output)

        except (json.decoder.JSONDecodeError, TypeError):
            self.label_message.setText('<i>Unhandled error happened!</i>')
            self.label_message.setVisible(True)
            self._track_error(error)

        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()


class TeamEditionAddChannelsPage(BasePage):

    def __init__(
            self,
            msg: str = 'Select default channels to be used',
            btn_add_msg: str = 'Add Channels',
            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('Skip')
        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.skip)
        self.button_add.clicked.connect(self.add_channels)

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

    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.create_login_data(default_channels, channels)
        self.accept()
