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

# yapf: disable

# Standard library imports
import datetime
from collections import OrderedDict

# Third party imports
import pytest
from unittest import mock

# Local imports
from anaconda_navigator.api.anaconda_api import _AnacondaAPI
from anaconda_navigator.utils.fixtures import tmpfolder


# yapf: enable

DEFAULT_TIMEOUT = 120000
tmpfolder

# --- Fixtures
# -----------------------------------------------------------------------------
@pytest.fixture
def api(tmpfolder):
    api = _AnacondaAPI()
    return api


# --- Tests
# -----------------------------------------------------------------------------


def test_conda_data(qtbot, api):
    """"""
    def output_ready(worker, output, error):
        assert error is None
        assert len(output)
        assert 'info' in output
        assert 'processed_info' in output
        assert 'packages' in output
        assert 'applications' in output

    worker = api.conda_data(prefix=api.ROOT_PREFIX)
    with qtbot.waitSignal(worker.sig_chain_finished, timeout=DEFAULT_TIMEOUT, raising=True):
        worker.sig_chain_finished.connect(output_ready)


def test_process_packages(api, qtbot):
    BLACKLIST = ['python', 'anaconda-navigator']

    def conda_data_ready(worker, output, error):
        packages = output['packages']
        worker_2 = api.process_packages(
            packages,
            prefix=api.ROOT_PREFIX,
            blacklist=BLACKLIST,
        )
        worker_2.check_packages = packages

        with qtbot.waitSignal(worker_2.sig_chain_finished, timeout=DEFAULT_TIMEOUT, raising=True):
            worker_2.sig_chain_finished.connect(process_packages_ready)

    def process_packages_ready(worker, output, error):
        assert error is None
        assert len(output)
        # See: https://github.com/ContinuumIO/navigator/issues/1244
        for package_name in BLACKLIST:
            assert package_name in worker.check_packages

    worker = api.conda_data(prefix=api.ROOT_PREFIX)
    with qtbot.waitSignal(worker.sig_chain_finished, timeout=DEFAULT_TIMEOUT, raising=True):
        worker.sig_chain_finished.connect(conda_data_ready)


def test_filter_environments(api):
    not_filtered_envs = OrderedDict()
    not_filtered_envs['some_env_path1'] = '_build_env'
    not_filtered_envs['some_env_path2'] = '__build_env'
    not_filtered_envs['some_env_path3'] = 'build_env'
    not_filtered_envs['some_env_path4'] = 'build_env_'
    not_filtered_envs['some_env_path5'] = 'build_env__'
    not_filtered_envs['some_env_path6'] = '__build_env2'
    not_filtered_envs['some_env_path7'] = '__build_env3__'

    filtered_envs = api.filter_environments(not_filtered_envs)

    assert len(filtered_envs) == 3
    assert filtered_envs['some_env_path3'] == 'build_env'
    assert filtered_envs['some_env_path4'] == 'build_env_'
    assert filtered_envs['some_env_path5'] == 'build_env__'


def test_process_unsafe_channels_default_condarc(api):
    channels = [
        'https://repo.anaconda.com/pkgs/main/osx-64', 'https://repo.anaconda.com/pkgs/main/noarch',
        'https://repo.anaconda.com/pkgs/r/osx-64', 'https://repo.anaconda.com/pkgs/r/noarch',
        'https://repo.anaconda.com/pkgs/msys2/osx-64', 'https://repo.anaconda.com/pkgs/msys2/noarch'
    ]

    unsafe_channels = [
        'defaults', 'https://repo.anaconda.com/pkgs/main', 'https://repo.anaconda.com/pkgs/r',
        'https://repo.anaconda.com/pkgs/msys2'
    ]

    processed_channels = api._process_unsafe_channels(channels, unsafe_channels)

    expected_processed_channels = [
        'https://repo.anaconda.com/pkgs/main/osx-64', 'https://repo.anaconda.com/pkgs/main/noarch',
        'https://repo.anaconda.com/pkgs/r/osx-64', 'https://repo.anaconda.com/pkgs/r/noarch',
        'https://repo.anaconda.com/pkgs/msys2/osx-64', 'https://repo.anaconda.com/pkgs/msys2/noarch'
    ]
    assert processed_channels == expected_processed_channels


def test_process_unsafe_channels_ate_private_channels(api):
    channels = [
        'https://repo.anaconda.com/pkgs/main/osx-64', 'https://repo.anaconda.com/pkgs/main/noarch',
        'https://repo.anaconda.com/pkgs/r/osx-64', 'https://repo.anaconda.com/pkgs/r/noarch',
        'https://repo.anaconda.com/pkgs/msys2/osx-64', 'https://repo.anaconda.com/pkgs/msys2/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/noarch'
    ]
    unsafe_channels = [
        'defaults',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco',
        'https://repo.anaconda.com/pkgs/main', 'https://repo.anaconda.com/pkgs/r',
        'https://repo.anaconda.com/pkgs/msys2'
    ]

    processed_channels = api._process_unsafe_channels(channels, unsafe_channels)

    expected_processed_channels = [
        'https://repo.anaconda.com/pkgs/main/osx-64', 'https://repo.anaconda.com/pkgs/main/noarch',
        'https://repo.anaconda.com/pkgs/r/osx-64', 'https://repo.anaconda.com/pkgs/r/noarch',
        'https://repo.anaconda.com/pkgs/msys2/osx-64', 'https://repo.anaconda.com/pkgs/msys2/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/noarch'
    ]
    assert processed_channels == expected_processed_channels


def test_process_unsafe_channels_ate_channels_in_channels(api):
    channels = [
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/main/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/main/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/r/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/r/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/msys2/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/msys2/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/noarch'
    ]
    unsafe_channels = [
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco',
        'https://repo.anaconda.com/pkgs/main', 'https://repo.anaconda.com/pkgs/r',
        'https://repo.anaconda.com/pkgs/msys2'
    ]

    processed_channels = api._process_unsafe_channels(channels, unsafe_channels)

    expected_processed_channels = [
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/noarch'
    ]
    assert processed_channels == expected_processed_channels


def test_process_unsafe_channels_ate_channels_in_default_channels(api):
    channels = [
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/main/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/main/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/r/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/r/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/msys2/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/msys2/noarch',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/<TOKEN>/api/repo/adefusco/noarch'
    ]
    unsafe_channels = [
        'defaults',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2'
    ]

    processed_channels = api._process_unsafe_channels(channels, unsafe_channels)

    expected_processed_channels = [
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/main/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/r/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/msys2/noarch',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/osx-64',
        'https://ate.training.anaconda.com/t/90e35a25a887f7bdc0db7f883347f84ca0db964f88af3620/api/repo/adefusco/noarch'
    ]
    assert processed_channels == expected_processed_channels


def test_process_unsafe_channels_ce_channels(api):
    channels = [
        'https://repo.anaconda.cloud/t/<TOKEN>/repo/main/osx-64',
        'https://repo.anaconda.cloud/t/<TOKEN>/repo/main/noarch',
        'https://repo.anaconda.cloud/t/<TOKEN>/repo/msys2/osx-64',
        'https://repo.anaconda.cloud/t/<TOKEN>/repo/msys2/noarch',
        'https://repo.anaconda.cloud/t/<TOKEN>/repo/r/osx-64', 'https://repo.anaconda.cloud/t/<TOKEN>/repo/r/noarch'
    ]
    unsafe_channels = [
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/main',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/msys2',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/r',
        'https://repo.anaconda.com/pkgs/main', 'https://repo.anaconda.com/pkgs/r',
        'https://repo.anaconda.com/pkgs/msys2'
    ]
    processed_channels = api._process_unsafe_channels(channels, unsafe_channels)

    expected_processed_channels = [
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/main/osx-64',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/main/noarch',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/msys2/osx-64',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/msys2/noarch',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/r/osx-64',
        'https://repo.anaconda.cloud/t/fc96b40a762d3826b7d958114336549769188541017cc3ef/repo/r/noarch'
    ]

    assert processed_channels == expected_processed_channels


def test_setup_commercial_edition_default_channels(api):
    config_default_channels_mock = mock.patch('anaconda_navigator.api.anaconda_api.configure_default_channels').start()

    with mock.patch.object(api._conda_api, 'load_rc'):
        api._conda_api.load_rc.return_value = {'default_channels': []}
        api.setup_commercial_edition_default_channels()
        config_default_channels_mock.assert_called()

        config_default_channels_mock.reset_mock()

        api._conda_api.load_rc.return_value = {
            'default_channels': [api.config.get('main', 'commercial_edition_url') + "/repo/test/path"]
        }
        api.setup_commercial_edition_default_channels()
        config_default_channels_mock.assert_not_called()


def test_detect_commercial_edition_login(api):
    commercial_edition_base_url = api.config.get('main', 'commercial_edition_url')
    token_list_mock = mock.patch('anaconda_navigator.api.anaconda_api.token_list').start()

    with mock.patch.object(api._conda_api, 'load_rc'), \
            mock.patch.object(api, 'setup_commercial_edition_default_channels'), mock.patch.object(api.config, 'set'):

        token_list_mock.return_value = {}
        api.detect_commercial_edition_login()
        api.setup_commercial_edition_default_channels.assert_not_called()
        api.config.set.assert_not_called()

        api.setup_commercial_edition_default_channels.reset_mock()
        api.config.set.reset_mock()

        token_list_mock.return_value = {commercial_edition_base_url: 'secret_ce_token'}
        api.detect_commercial_edition_login()
        api.setup_commercial_edition_default_channels.assert_called()
        api.config.set.assert_has_calls(
            (mock.call('main', 'logged_brand', 'Commercial Edition'),
             mock.call('main', 'logged_api_url', commercial_edition_base_url)),
            any_order=True
        )
