# -*- coding: utf-8 -*-

# -----------------------------------------------------------------------------
# Copyright (c) 2016-2017 Anaconda, Inc.
#
# May be copied and distributed freely only as part of an Anaconda or
# Miniconda installation.
# -----------------------------------------------------------------------------
"""Anaconda Nucleus login dialogs."""

__all__ = ['NucleusLoginPage']

import typing
import requests
from qtpy.QtCore import Qt
from qtpy.QtWidgets import QApplication, QWidget
from anaconda_navigator.api import nucleus as nucleus_api
from anaconda_navigator.config import CONF, NUCLEUS_BRAND
from anaconda_navigator.static.images import ANACONDA_NUCLEUS_LOGIN_LOGO
from .base_dialogs import BaseLoginPage
from .utils import TextContainer


NUCLEUS_LOGIN_TEXT_CONTAINER = TextContainer(
    title='Sign In',
    info_frame_text=(
        'Log into Anaconda Nucleus to backup your environment and access more data science tools. If you don’t have '
        'an account, click <a href="{}" style="color:#43B049;text-decoration: none">here</a>.'
    ),
    form_forgot_links_msg=(
        'Forget your <a href="{password_url}" style="color:#43B049; text-decoration:none">password</a>?'
    ),
    message_box_error_text='The Anaconda Nucleus API domain is not specified! Please, set in preferences.',
    header_frame_logo_path=ANACONDA_NUCLEUS_LOGIN_LOGO,
)


class NucleusLoginPage(BaseLoginPage):

    def __init__(self, parent: typing.Optional[QWidget] = None) -> None:
        """Initialize new :class:`~NucleusLoginPage` instance."""
        super().__init__(nucleus_api.NucleusAPI(), NUCLEUS_LOGIN_TEXT_CONTAINER, parent=parent)
        self.label_login.setText('Email')
        self.text_login.setValidator(None)

        self.api_url_config_option = 'nucleus_base_url'
        self.brand = NUCLEUS_BRAND

        self.finished.connect(self.__finished)

    def login(self):
        base_url = CONF.get('main', self.api_url_config_option)
        if not base_url:
            self._show_message_box(title='Login Error', text=self.text_container.domain_not_found_msg)
            return

        self.button_login.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)

        self.label_message.setText('')
        self.label_message.setVisible(False)

        text_login: str = self.text_login.text().lower()
        self.text_login.setText(text_login)

        worker: nucleus_api.TaskWorker = self.api.login.worker(
            username=text_login,
            password=self.text_password.text(),
        )
        self.finished.connect(worker.cancel)
        worker.signals.sig_done.connect(lambda result: self.finished.disconnect(worker.cancel))
        worker.signals.sig_done.connect(self.__process_login_response)
        worker.start()

    def __process_login_response(self, result: nucleus_api.TaskResult) -> None:
        """Check response from Nucleus server for login."""
        if not self.isVisible():
            return

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

        error_msg: typing.Optional[str] = None
        if result.status != nucleus_api.TaskStatus.SUCCEEDED:
            error: BaseException = result.exception
            error_msg = str(error)
            if isinstance(error, requests.RequestException) and (error.response is not None):
                if error.response.status_code in (401, 403):
                    error_msg = 'Invalid credentials'

        if self.api.token.valid:
            self.accept()
            return

        if error_msg is not None:
            self.label_message.setText(error_msg)
            self.label_message.setVisible(True)

            url: str = CONF.get('main', self.api_url_config_option, '-')
            username: str = result.call.kwargs['username']
            self.tracker.track_event('authenticate', 'login failed', label=f'{url}/{username}: {error_msg.lower()}')

            self.text_password.setFocus()
            self.text_password.selectAll()

    def __finished(self) -> None:
        """Update dialog state when it is closed."""
        QApplication.restoreOverrideCursor()

    def update_links(self):
        """Update links."""

        base_url = CONF.get('main', 'nucleus_base_url', None)

        if not base_url:
            return

        base_url = base_url.rstrip('/')
        forgot_links_updated_text = self.forgot_links.text().format(
            password_url=base_url + '/forgot-password'
        )
        info_updated_text = self.label_information.text().format(base_url + '/sign-up')
        self.label_information.setText(info_updated_text)
        self.forgot_links.setText(forgot_links_updated_text)

        self.label_information.linkActivated.connect(lambda activated_link: self.open_url(activated_link))
        self.forgot_links.linkActivated.connect(lambda activated_link: self.open_url(activated_link))
