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

import base64
import json
import os
import os.path
import random
import shutil
import tempfile
import unittest

from docker import auth, credentials, errors
import pytest

try:
    from unittest import mock
except ImportError:
    import mock


class RegressionTest(unittest.TestCase):
    def test_803_urlsafe_encode(self):
        auth_data = {
            'username': 'root',
            'password': 'GR?XGR?XGR?XGR?X'
        }
        encoded = auth.encode_header(auth_data)
        assert b'/' not in encoded
        assert b'_' in encoded


class ResolveRepositoryNameTest(unittest.TestCase):
    def test_resolve_repository_name_hub_library_image(self):
        assert auth.resolve_repository_name('image') == (
            'docker.io', 'image'
        )

    def test_resolve_repository_name_dotted_hub_library_image(self):
        assert auth.resolve_repository_name('image.valid') == (
            'docker.io', 'image.valid'
        )

    def test_resolve_repository_name_hub_image(self):
        assert auth.resolve_repository_name('username/image') == (
            'docker.io', 'username/image'
        )

    def test_explicit_hub_index_library_image(self):
        assert auth.resolve_repository_name('docker.io/image') == (
            'docker.io', 'image'
        )

    def test_explicit_legacy_hub_index_library_image(self):
        assert auth.resolve_repository_name('index.docker.io/image') == (
            'docker.io', 'image'
        )

    def test_resolve_repository_name_private_registry(self):
        assert auth.resolve_repository_name('my.registry.net/image') == (
            'my.registry.net', 'image'
        )

    def test_resolve_repository_name_private_registry_with_port(self):
        assert auth.resolve_repository_name('my.registry.net:5000/image') == (
            'my.registry.net:5000', 'image'
        )

    def test_resolve_repository_name_private_registry_with_username(self):
        assert auth.resolve_repository_name(
            'my.registry.net/username/image'
        ) == ('my.registry.net', 'username/image')

    def test_resolve_repository_name_no_dots_but_port(self):
        assert auth.resolve_repository_name('hostname:5000/image') == (
            'hostname:5000', 'image'
        )

    def test_resolve_repository_name_no_dots_but_port_and_username(self):
        assert auth.resolve_repository_name(
            'hostname:5000/username/image'
        ) == ('hostname:5000', 'username/image')

    def test_resolve_repository_name_localhost(self):
        assert auth.resolve_repository_name('localhost/image') == (
            'localhost', 'image'
        )

    def test_resolve_repository_name_localhost_with_username(self):
        assert auth.resolve_repository_name('localhost/username/image') == (
            'localhost', 'username/image'
        )

    def test_invalid_index_name(self):
        with pytest.raises(errors.InvalidRepository):
            auth.resolve_repository_name('-gecko.com/image')


def encode_auth(auth_info):
    return base64.b64encode(
        auth_info.get('username', '').encode('utf-8') + b':' +
        auth_info.get('password', '').encode('utf-8'))


class ResolveAuthTest(unittest.TestCase):
    index_config = {'auth': encode_auth({'username': 'indexuser'})}
    private_config = {'auth': encode_auth({'username': 'privateuser'})}
    legacy_config = {'auth': encode_auth({'username': 'legacyauth'})}

    auth_config = auth.AuthConfig({
        'auths': auth.parse_auth({
            'https://index.docker.io/v1/': index_config,
            'my.registry.net': private_config,
            'http://legacy.registry.url/v1/': legacy_config,
        })
    })

    def test_resolve_authconfig_hostname_only(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'my.registry.net'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_no_protocol(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'my.registry.net/v1/'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_no_path(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'http://my.registry.net'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_no_path_trailing_slash(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'http://my.registry.net/'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_no_path_wrong_secure_proto(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'https://my.registry.net'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_no_path_wrong_insecure_proto(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'http://index.docker.io'
        )['username'] == 'indexuser'

    def test_resolve_authconfig_path_wrong_proto(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'https://my.registry.net/v1/'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_default_registry(self):
        assert auth.resolve_authconfig(
            self.auth_config
        )['username'] == 'indexuser'

    def test_resolve_authconfig_default_explicit_none(self):
        assert auth.resolve_authconfig(
            self.auth_config, None
        )['username'] == 'indexuser'

    def test_resolve_authconfig_fully_explicit(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'http://my.registry.net/v1/'
        )['username'] == 'privateuser'

    def test_resolve_authconfig_legacy_config(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'legacy.registry.url'
        )['username'] == 'legacyauth'

    def test_resolve_authconfig_no_match(self):
        assert auth.resolve_authconfig(
            self.auth_config, 'does.not.exist'
        ) is None

    def test_resolve_registry_and_auth_library_image(self):
        image = 'image'
        assert auth.resolve_authconfig(
            self.auth_config, auth.resolve_repository_name(image)[0]
        )['username'] == 'indexuser'

    def test_resolve_registry_and_auth_hub_image(self):
        image = 'username/image'
        assert auth.resolve_authconfig(
            self.auth_config, auth.resolve_repository_name(image)[0]
        )['username'] == 'indexuser'

    def test_resolve_registry_and_auth_explicit_hub(self):
        image = 'docker.io/username/image'
        assert auth.resolve_authconfig(
            self.auth_config, auth.resolve_repository_name(image)[0]
        )['username'] == 'indexuser'

    def test_resolve_registry_and_auth_explicit_legacy_hub(self):
        image = 'index.docker.io/username/image'
        assert auth.resolve_authconfig(
            self.auth_config, auth.resolve_repository_name(image)[0]
        )['username'] == 'indexuser'

    def test_resolve_registry_and_auth_private_registry(self):
        image = 'my.registry.net/image'
        assert auth.resolve_authconfig(
            self.auth_config, auth.resolve_repository_name(image)[0]
        )['username'] == 'privateuser'

    def test_resolve_registry_and_auth_unauthenticated_registry(self):