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

    Copyright (C) 2014-2016 bromix (plugin.video.youtube)
    Copyright (C) 2016-2018 plugin.video.youtube

    SPDX-License-Identifier: GPL-2.0-only
    See LICENSES/GPL-2.0-only for more information.
"""

from six.moves import range

import copy
import json
import time
from ...youtube.youtube_exceptions import LoginException


def process(mode, provider, context, sign_out_refresh=True):
    addon_id = context.get_param('addon_id', None)

    def _do_logout():
        # we clear the cache, so none cached data of an old account will be displayed.
        provider.get_resource_manager(context).clear()

        signout_access_manager = context.get_access_manager()
        if addon_id:
            if signout_access_manager.developer_has_refresh_token(addon_id):
                refresh_tokens = signout_access_manager.get_dev_refresh_token(addon_id).split('|')
                refresh_tokens = list(set(refresh_tokens))
                for _refresh_token in refresh_tokens:
                    provider.get_client(context).revoke(_refresh_token)
        else:
            if signout_access_manager.has_refresh_token():
                refresh_tokens = signout_access_manager.get_refresh_token().split('|')
                refresh_tokens = list(set(refresh_tokens))
                for _refresh_token in refresh_tokens:
                    provider.get_client(context).revoke(_refresh_token)

        provider.reset_client()

        if addon_id:
            signout_access_manager.update_dev_access_token(addon_id, access_token='', refresh_token='')
        else:
            signout_access_manager.update_access_token(access_token='', refresh_token='')

    def _do_login(_for_tv=False):
        _client = provider.get_client(context)

        try:
            if _for_tv:
                json_data = _client.request_device_and_user_code_tv()
            else:
                json_data = _client.request_device_and_user_code()
        except LoginException:
            _do_logout()
            raise

        interval = int(json_data.get('interval', 5)) * 1000
        if interval > 60000:
            interval = 5000
        device_code = json_data['device_code']
        user_code = json_data['user_code']

        text = [context.localize(provider.LOCAL_MAP['youtube.sign.go_to']) % context.get_ui().bold('youtube.com/activate'),
                '[CR]%s %s' % (context.localize(provider.LOCAL_MAP['youtube.sign.enter_code']), context.get_ui().bold(user_code))]
        text = ''.join(text)
        dialog = context.get_ui().create_progress_dialog(
            heading=context.localize(provider.LOCAL_MAP['youtube.sign.in']), text=text, background=False)

        steps = ((10 * 60 * 1000) // interval)  # 10 Minutes
        dialog.set_total(steps)
        for i in range(steps):
            dialog.update()
            try:
                if _for_tv:
                    json_data = _client.request_access_token_tv(device_code)
                else:
                    json_data = _client.request_access_token(device_code)
            except LoginException:
                _do_logout()
                raise

            log_data = copy.deepcopy(json_data)
            if 'access_token' in log_data:
                log_data['access_token'] = '<redacted>'
            if 'refresh_token' in log_data:
                log_data['refresh_token'] = '<redacted>'
            context.log_debug('Requesting access token: |%s|' % json.dumps(log_data))

            if 'error' not in json_data:
                _access_token = json_data.get('access_token', '')
                _expires_in = time.time() + int(json_data.get('expires_in', 3600))
                _refresh_token = json_data.get('refresh_token', '')
                dialog.close()
                if not _access_token and not _refresh_token:
                    _expires_in = 0
                return _access_token, _expires_in, _refresh_token

            elif json_data['error'] != u'authorization_pending':
                message = json_data['error']
                title = '%s: %s' % (context.get_name(), message)
                context.get_ui().show_notification(message, title)
                context.log_error('Error requesting access token: |%s|' % message)

            if dialog.is_aborted():
                dialog.close()
                return '', 0, ''

            context.sleep(interval)
        dialog.close()

    if mode == 'out':
        _do_logout()
        if sign_out_refresh:
            context.get_ui().refresh_container()

    elif mode == 'in':
        context.get_ui().on_ok(context.localize(provider.LOCAL_MAP['youtube.sign.twice.title']),
                               context.localize(provider.LOCAL_MAP['youtube.sign.twice.text']))

        access_token_tv, expires_in_tv, refresh_token_tv = _do_login(_for_tv=True)
        # abort tv login
        context.log_debug('YouTube-TV Login: Access Token |%s| Refresh Token |%s| Expires |%s|' % (access_token_tv != '', refresh_token_tv != '', expires_in_tv))
        if not access_token_tv and not refresh_token_tv:
            provider.reset_client()
            if addon_id:
                context.get_access_manager().update_dev_access_token(addon_id, '')
            else:
                context.get_access_manager().update_access_token('')
            context.get_ui().refresh_container()
            return

        access_token_kodi, expires_in_kodi, refresh_token_kodi = _do_login(_for_tv=False)
        # abort kodi login
        context.log_debug('YouTube-Kodi Login: Access Token |%s| Refresh Token |%s| Expires |%s|' % (access_token_kodi != '', refresh_token_kodi != '', expires_in_kodi))
        if not access_token_kodi and not refresh_token_kodi:
            provider.reset_client()
            if addon_id:
                context.get_access_manager().update_dev_access_token(addon_id, '')
            else:
                context.get_access_manager().update_access_token('')
            context.get_ui().refresh_container()
            return

        access_token = '%s|%s' % (access_token_tv, access_token_kodi)
        refresh_token = '%s|%s' % (refresh_token_tv, refresh_token_kodi)
        expires_in = min(expires_in_tv, expires_in_kodi)

        # we clear the cache, so none cached data of an old account will be displayed.
        provider.get_resource_manager(context).clear()

        provider.reset_client()

        if addon_id:
            context.get_access_manager().update_dev_access_token(addon_id, access_token, expires_in, refresh_token)
        else:
            context.get_access_manager().update_access_token(access_token, expires_in, refresh_token)

        context.get_ui().refresh_container()
