import time
from cattle.plugins.docker.network import setup_mac_and_ip
from cattle.plugins.host_info.main import HostInfo
from cattle.plugins.docker.util import remove_container
from cattle.plugins.docker.compute import DockerCompute

from .common_fixtures import *  # NOQA
from .docker_common import *  # NOQA
from docker.errors import APIError


@pytest.fixture(scope='module')
def pull_images():
    client = docker_client()
    images = [('ibuildthecloud/helloworld', 'latest'),
              ('rancher/agent', 'v0.7.11'),
              ('rancher/agent-instance', 'v0.3.1')]
    for i in images:
        client.pull(i[0], i[1])


@if_docker
def test_volume_activate(agent, responses):
    event_test(agent, 'docker/volume_activate')


@if_docker
def test_volume_deactivate(agent, responses):
    event_test(agent, 'docker/volume_deactivate')


@if_docker
def test_instance_activate_no_mac_address(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def pre(req):
        instance = req['data']['instanceHostMap']['instance']
        for nic in instance['nics']:
            nic['macAddress'] = ''

    def post(req, resp):
        instance_data = resp['data']['instanceHostMap']['instance']['+data']
        docker_inspect = instance_data['dockerInspect']
        mac_received = docker_inspect['Config']['MacAddress']
        mac_nic_received = docker_inspect['NetworkSettings']['MacAddress']
        assert mac_received == ''
        assert mac_nic_received is not None
        instance_activate_common_validation(resp)

    event_test(agent, 'docker/instance_activate', pre_func=pre, post_func=post)


@if_docker
def test_instance_activate_mac_address(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def post(req, resp):
        instance_data = resp['data']['instanceHostMap']['instance']['+data']
        docker_inspect = instance_data['dockerInspect']
        mac_received = docker_inspect['Config']['MacAddress']
        mac_nic_received = docker_inspect['NetworkSettings']['MacAddress']
        assert mac_nic_received == '02:03:04:05:06:07'
        assert mac_received == '02:03:04:05:06:07'
        instance_activate_common_validation(resp)

    event_test(agent, 'docker/instance_activate', post_func=post)


def test_multiple_nics_pick_mac():
    instance = {
        'nics': [
            {
                'macAddress': '02:03:04:05:06:07',
                'deviceNumber': 0
            },
            {
                'macAddress': '02:03:04:05:06:09',
                'deviceNumber': 1
            }
        ]
    }
    instance = JsonObject(instance)
    config = {'test': 'Nothing'}
    setup_mac_and_ip(instance, config)
    assert config['mac_address'] == '02:03:04:05:06:07'


@if_docker
def test_instance_activate_ports(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def post(req, resp):
        instance_data = resp['data']['instanceHostMap']['instance']['+data']
        del instance_data['dockerInspect']
        docker_container = instance_data['dockerContainer']
        fields = instance_data['+fields']
        del docker_container['Created']
        del docker_container['Id']
        del docker_container['Status']
        del fields['dockerIp']
        del resp['data']['instanceHostMap']['instance']['externalId']

        assert len(docker_container['Ports']) == 1
        assert docker_container['Ports'][0]['PrivatePort'] == 8080
        assert docker_container['Ports'][0]['Type'] == 'tcp'

    event_test(agent, 'docker/instance_activate_ports', post_func=post)


@if_docker
def test_instance_activate_links_null_ports(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def pre(req):
        links = req.data.instanceHostMap.instance.instanceLinks
        links.append(JsonObject({
            'type': 'instanceLink',
            'linkName': 'null',
            'data': {
                'fields': {
                    'ports': None
                }
            },
            'targetInstanceId': None,
        }))

    def post(req, resp):
        id = resp['data']['instanceHostMap']['instance']
        id = id['+data']['dockerContainer']['Id']
        instance_activate_common_validation(resp)

    event_test(agent, 'docker/instance_activate_links', pre_func=pre,
               post_func=post)


@if_docker
def test_instance_activate_double_links(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def post(req, resp):
        id = resp['data']['instanceHostMap']['instance']
        id = id['+data']['dockerContainer']['Id']
        inspect = docker_client().inspect_container(id)
        instance_activate_common_validation(resp)

        env = inspect['Config']['Env']

        for line in env:
            assert 'LVL' not in line

        assert 'MYSQL_NAME=/cattle/mysql' in env
        assert 'MYSQL_PORT=udp://mysql:3307' in env
        assert 'MYSQL_PORT_3307_UDP=udp://mysql:3307' in env
        assert 'MYSQL_PORT_3307_UDP_ADDR=mysql' in env
        assert 'MYSQL_PORT_3307_UDP_PORT=3307' in env
        assert 'MYSQL_PORT_3307_UDP_PROTO=udp' in env

        assert 'MYSQL_PORT_3306_TCP=tcp://mysql:3306' in env
        assert 'MYSQL_PORT_3306_TCP_ADDR=mysql' in env
        assert 'MYSQL_PORT_3306_TCP_PORT=3306' in env
        assert 'MYSQL_PORT_3306_TCP_PROTO=tcp' in env

        assert 'REDIS_NAME=/cattle/redis' in env
        assert 'REDIS_PORT=udp://redis:26' in env
        assert 'REDIS_PORT_26_UDP=udp://redis:26' in env
        assert 'REDIS_PORT_26_UDP_ADDR=redis' in env
        assert 'REDIS_PORT_26_UDP_PORT=26' in env
        assert 'REDIS_PORT_26_UDP_PROTO=udp' in env

        assert 'REDIS_ENV_ONE=TWO' in env
        assert 'REDIS_ENV_THREE=FOUR' in env
        assert 'REDIS_1_ENV_ONE=TWO' in env
        assert 'REDIS_1_ENV_THREE=FOUR' in env
        assert 'REDIS_2_ENV_ONE=TWO' in env
        assert 'REDIS_2_ENV_THREE=FOUR' in env
        assert 'ENV_REDIS_1_ENV_ONE=TWO' in env
        assert 'ENV_REDIS_1_ENV_THREE=FOUR' in env
        assert 'ENV_REDIS_2_ENV_ONE=TWO' in env
        assert 'ENV_REDIS_2_ENV_THREE=FOUR' in env

        assert 'REDIS_1_PORT=udp://redis:26' in env
        assert 'REDIS_1_PORT_26_UDP=udp://redis:26' in env
        assert 'REDIS_1_PORT_26_UDP_ADDR=redis' in env
        assert 'REDIS_1_PORT_26_UDP_PORT=26' in env
        assert 'REDIS_1_PORT_26_UDP_PROTO=udp' in env

        assert 'ENV_REDIS_1_PORT=udp://redis:26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP=udp://redis:26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_ADDR=redis' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_PORT=26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_PROTO=udp' in env

    event_test(agent, 'docker/instance_activate_double_links', post_func=post)


@if_docker
def test_instance_activate_links(agent, responses):
    delete_container('/c861f990-4472-4fa1-960f-65171b544c28')

    def post(req, resp):
        id = resp['data']['instanceHostMap']['instance']
        id = id['+data']['dockerContainer']['Id']
        inspect = docker_client().inspect_container(id)
        instance_activate_common_validation(resp)

        env = inspect['Config']['Env']

        assert 'MYSQL_NAME=/cattle/mysql' in env
        assert 'MYSQL_PORT=udp://mysql:3307' in env
        assert 'MYSQL_PORT_3307_UDP=udp://mysql:3307' in env
        assert 'MYSQL_PORT_3307_UDP_ADDR=mysql' in env
        assert 'MYSQL_PORT_3307_UDP_PORT=3307' in env
        assert 'MYSQL_PORT_3307_UDP_PROTO=udp' in env

        assert 'MYSQL_PORT_3306_TCP=tcp://mysql:3306' in env
        assert 'MYSQL_PORT_3306_TCP_ADDR=mysql' in env
        assert 'MYSQL_PORT_3306_TCP_PORT=3306' in env
        assert 'MYSQL_PORT_3306_TCP_PROTO=tcp' in env

        assert 'REDIS_NAME=/cattle/redis' in env
        assert 'REDIS_PORT=udp://redis:26' in env
        assert 'REDIS_PORT_26_UDP=udp://redis:26' in env
        assert 'REDIS_PORT_26_UDP_ADDR=redis' in env
        assert 'REDIS_PORT_26_UDP_PORT=26' in env
        assert 'REDIS_PORT_26_UDP_PROTO=udp' in env

        assert 'REDIS_ENV_ONE=TWO' in env
        assert 'REDIS_ENV_THREE=FOUR' in env
        assert 'REDIS_1_ENV_ONE=TWO' in env
        assert 'REDIS_1_ENV_THREE=FOUR' in env
        assert 'REDIS_2_ENV_ONE=TWO' in env
        assert 'REDIS_2_ENV_THREE=FOUR' in env
        assert 'ENV_REDIS_1_ENV_ONE=TWO' in env
        assert 'ENV_REDIS_1_ENV_THREE=FOUR' in env
        assert 'ENV_REDIS_2_ENV_ONE=TWO' in env
        assert 'ENV_REDIS_2_ENV_THREE=FOUR' in env

        assert 'REDIS_1_PORT=udp://redis:26' in env
        assert 'REDIS_1_PORT_26_UDP=udp://redis:26' in env
        assert 'REDIS_1_PORT_26_UDP_ADDR=redis' in env
        assert 'REDIS_1_PORT_26_UDP_PORT=26' in env
        assert 'REDIS_1_PORT_26_UDP_PROTO=udp' in env

        assert 'ENV_REDIS_1_PORT=udp://redis:26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP=udp://redis:26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_ADDR=redis' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_PORT=26' in env
        assert 'ENV_REDIS_1_PORT_26_UDP_PROTO=udp' in env

    event_test(agent, 'docker/instance_activate_links', post_func=post)


@if_docker
def test_instance_activate_links_no_service(agent, responses):