#
#
#

from __future__ import absolute_import, division, print_function, \
    unicode_literals

from dyn.tm.errors import DynectGetError
from dyn.tm.services.dsf import DSFResponsePool
from json import loads
from mock import MagicMock, call, patch
from unittest import TestCase

from octodns.record import Create, Delete, Record, Update
from octodns.provider.base import Plan
from octodns.provider.dyn import DynProvider, _CachingDynZone
from octodns.zone import Zone

from helpers import SimpleProvider


class _DummyPool(object):

    def __init__(self, response_pool_id):
        self.response_pool_id = response_pool_id
        self.deleted = False

    def delete(self):
        self.deleted = True


class TestDynProvider(TestCase):
    expected = Zone('unit.tests.', [])
    for name, data in (
        ('', {
            'type': 'A',
            'ttl': 300,
            'values': ['1.2.3.4']
        }),
        ('cname', {
            'type': 'CNAME',
            'ttl': 301,
            'value': 'unit.tests.'
        }),
        ('', {
            'type': 'MX',
            'ttl': 302,
            'values': [{
                'preference': 10,
                'exchange': 'smtp-1.unit.tests.'
            }, {
                'preference': 20,
                'exchange': 'smtp-2.unit.tests.'
            }]
        }),
        ('naptr', {
            'type': 'NAPTR',
            'ttl': 303,
            'values': [{
                'order': 100,
                'preference': 101,
                'flags': 'U',
                'service': 'SIP+D2U',
                'regexp': '!^.*$!sip:info@foo.example.com!',
                'replacement': '.',
            }, {
                'order': 200,
                'preference': 201,
                'flags': 'U',
                'service': 'SIP+D2U',
                'regexp': '!^.*$!sip:info@bar.example.com!',
                'replacement': '.',
            }]
        }),
        ('sub', {
            'type': 'NS',
            'ttl': 3600,
            'values': ['ns3.p10.dynect.net.', 'ns3.p10.dynect.net.'],
        }),
        ('ptr', {
            'type': 'PTR',
            'ttl': 304,
            'value': 'xx.unit.tests.'
        }),
        ('spf', {
            'type': 'SPF',
            'ttl': 305,
            'values': ['v=spf1 ip4:192.168.0.1/16-all', 'v=spf1 -all'],
        }),
        ('', {
            'type': 'SSHFP',
            'ttl': 306,
            'value': {
                'algorithm': 1,
                'fingerprint_type': 1,
                'fingerprint': 'bf6b6825d2977c511a475bbefb88aad54a92ac73',
            }
        }),
        ('_srv._tcp', {
            'type': 'SRV',
            'ttl': 307,
            'values': [{
                'priority': 11,
                'weight': 12,
                'port': 10,
                'target': 'foo-1.unit.tests.'
            }, {
                'priority': 21,
                'weight': 22,
                'port': 20,
                'target': 'foo-2.unit.tests.'
            }]}),
        ('', {
            'type': 'CAA',
            'ttl': 308,
            'values': [{
                'flags': 0,
                'tag': 'issue',
                'value': 'ca.unit.tests'
            }]})):
        expected.add_record(Record.new(expected, name, data))

    @classmethod
    def setUpClass(self):
        # Get the DynectSession creation out of the way so that tests can
        # ignore it
        with patch('dyn.core.SessionEngine.execute',
                   return_value={'status': 'success'}):
            provider = DynProvider('test', 'cust', 'user', 'pass')
            provider._check_dyn_sess()

    def setUp(self):
        # Flush our zone to ensure we start fresh
        _CachingDynZone.flush_zone(self.expected.name[:-1])

    @patch('dyn.core.SessionEngine.execute')
    def test_populate_non_existent(self, execute_mock):
        provider = DynProvider('test', 'cust', 'user', 'pass')

        # Test Zone create
        execute_mock.side_effect = [
            DynectGetError('foo'),
        ]
        got = Zone('unit.tests.', [])
        provider.populate(got)
        execute_mock.assert_has_calls([
            call('/Zone/unit.tests/', 'GET', {}),
        ])
        self.assertEquals(set(), got.records)

    @patch('dyn.core.SessionEngine.execute')
    def test_populate(self, execute_mock):
        provider = DynProvider('test', 'cust', 'user', 'pass')

        # Test Zone create
        execute_mock.side_effect = [
            # get Zone
            {'data': {}},
            # get_all_records
            {'data': {
                'a_records': [{
                    'fqdn': 'unit.tests',
                    'rdata': {'address': '1.2.3.4'},
                    'record_id': 1,
                    'record_type': 'A',
                    'ttl': 300,
                    'zone': 'unit.tests',
                }],
                'cname_records': [{
                    'fqdn': 'cname.unit.tests',
                    'rdata': {'cname': 'unit.tests.'},
                    'record_id': 2,
                    'record_type': 'CNAME',
                    'ttl': 301,
                    'zone': 'unit.tests',
                }],
                'ns_records': [{
                    'fqdn': 'unit.tests',
                    'rdata': {'nsdname': 'ns1.p10.dynect.net.'},
                    'record_id': 254597562,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }, {
                    'fqdn': 'unit.tests',
                    'rdata': {'nsdname': 'ns2.p10.dynect.net.'},
                    'record_id': 254597563,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }, {
                    'fqdn': 'unit.tests',
                    'rdata': {'nsdname': 'ns3.p10.dynect.net.'},
                    'record_id': 254597564,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }, {
                    'fqdn': 'unit.tests',
                    'rdata': {'nsdname': 'ns4.p10.dynect.net.'},
                    'record_id': 254597565,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }, {
                    'fqdn': 'sub.unit.tests',
                    'rdata': {'nsdname': 'ns3.p10.dynect.net.'},
                    'record_id': 254597564,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }, {
                    'fqdn': 'sub.unit.tests',
                    'rdata': {'nsdname': 'ns3.p10.dynect.net.'},
                    'record_id': 254597564,
                    'record_type': 'NS',
                    'service_class': '',
                    'ttl': 3600,
                    'zone': 'unit.tests'
                }],
                'mx_records': [{
                    'fqdn': 'unit.tests',
                    'rdata': {'exchange': 'smtp-1.unit.tests.',
                              'preference': 10},
                    'record_id': 3,
                    'record_type': 'MX',
                    'ttl': 302,
                    'zone': 'unit.tests',
                }, {
                    'fqdn': 'unit.tests',
                    'rdata': {'exchange': 'smtp-2.unit.tests.',
                              'preference': 20},
                    'record_id': 4,
                    'record_type': 'MX',
                    'ttl': 302,
                    'zone': 'unit.tests',
                }],
                'naptr_records': [{
                    'fqdn': 'naptr.unit.tests',
                    'rdata': {'flags': 'U',
                              'order': 100,
                              'preference': 101,
                              'regexp': '!^.*$!sip:info@foo.example.com!',
                              'replacement': '.',
                              'services': 'SIP+D2U'},
                    'record_id': 5,
                    'record_type': 'MX',
                    'ttl': 303,
                    'zone': 'unit.tests',
                }, {
                    'fqdn': 'naptr.unit.tests',
                    'rdata': {'flags': 'U',
                              'order': 200,
                              'preference': 201,
                              'regexp': '!^.*$!sip:info@bar.example.com!',
                              'replacement': '.',
                              'services': 'SIP+D2U'},
                    'record_id': 6,
                    'record_type': 'MX',
                    'ttl': 303,