#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import random
import time
import unittest

from mock import call
from mock import patch
from mock import MagicMock as Mock

import pyrax
from pyrax.manager import BaseManager
from pyrax.clouddns import assure_domain
from pyrax.clouddns import CloudDNSClient
from pyrax.clouddns import CloudDNSDomain
from pyrax.clouddns import CloudDNSManager
from pyrax.clouddns import CloudDNSRecord
from pyrax.clouddns import ResultsIterator
from pyrax.clouddns import DomainResultsIterator
from pyrax.clouddns import SubdomainResultsIterator
from pyrax.clouddns import RecordResultsIterator
import pyrax.exceptions as exc
import pyrax.utils as utils

from pyrax import fakes

example_uri = "http://example.com"


class CloudDNSTest(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super(CloudDNSTest, self).__init__(*args, **kwargs)

    def setUp(self):
        super(CloudDNSTest, self).setUp()
        self.client = fakes.FakeDNSClient()
        self.client._manager = fakes.FakeDNSManager(self.client)
        self.client._manager._set_delay(0.000001)
        self.domain = fakes.FakeDNSDomain()
        self.domain.manager = self.client._manager

    def tearDown(self):
        super(CloudDNSTest, self).tearDown()
        self.client = None
        self.domain = None

    def test_assure_domain(self):
        @assure_domain
        def test(self, domain):
            return domain
        clt = self.client
        dom = self.domain
        d1 = test(clt, dom)
        self.assertEqual(d1, dom)
        self.assertTrue(isinstance(d1, CloudDNSDomain))

    def test_assure_domain_id(self):
        @assure_domain
        def test(self, domain):
            return domain
        clt = self.client
        dom = self.domain
        clt._manager._get = Mock(return_value=dom)
        d2 = test(clt, dom.id)
        self.assertEqual(d2, dom)
        self.assertTrue(isinstance(d2, CloudDNSDomain))

    def test_assure_domain_name(self):
        @assure_domain
        def test(self, domain):
            return domain
        clt = self.client
        dom = self.domain
        clt._manager._get = Mock(side_effect=exc.NotFound(""))
        clt._manager._list = Mock(return_value=[dom])
        d3 = test(clt, dom.name)
        self.assertEqual(d3, dom)
        self.assertTrue(isinstance(d3, CloudDNSDomain))

    def test_set_timeout(self):
        clt = self.client
        mgr = clt._manager
        new_timeout = random.randint(0, 99)
        clt.set_timeout(new_timeout)
        self.assertEqual(mgr._timeout, new_timeout)

    def test_set_delay(self):
        clt = self.client
        mgr = clt._manager
        new_delay = random.randint(0, 99)
        clt.set_delay(new_delay)
        self.assertEqual(mgr._delay, new_delay)

    def test_reset_paging_all(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["domain"]["total_entries"] = 99
        mgr._paging["record"]["next_uri"] = example_uri
        mgr._reset_paging("all")
        self.assertIsNone(mgr._paging["domain"]["total_entries"])
        self.assertIsNone(mgr._paging["record"]["next_uri"])

    def test_reset_paging_body(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["domain"]["total_entries"] = 99
        mgr._paging["domain"]["next_uri"] = "FAKE"
        exp_entries = random.randint(100, 200)
        uri_string_next = utils.random_unicode()
        next_uri = "%s/domains/%s" % (example_uri, uri_string_next)
        uri_string_prev = utils.random_unicode()
        prev_uri = "%s/domains/%s" % (example_uri, uri_string_prev)
        body = {"totalEntries": exp_entries,
                "links": [
                    {"href": next_uri,
                    "rel": "next"},
                    {"href": prev_uri,
                    "rel": "previous"}]}
        mgr._reset_paging("domain", body=body)
        self.assertEqual(mgr._paging["domain"]["total_entries"], exp_entries)
        self.assertEqual(mgr._paging["domain"]["next_uri"], "/domains/%s" %
                uri_string_next)
        self.assertEqual(mgr._paging["domain"]["prev_uri"], "/domains/%s" %
                uri_string_prev)

    def test_get_pagination_qs(self):
        clt = self.client
        mgr = clt._manager
        test_limit = random.randint(1, 100)
        test_offset = random.randint(1, 100)
        qs
 = mgr._get_pagination_qs(test_limit, test_offset)
        self.assertEqual(qs, "?limit=%s&offset=%s" % (test_limit, test_offset))

    def test_manager_list(self):
        clt = self.client
        mgr = clt._manager
        fake_name = utils.random_unicode()
        re
t_body = {"domains": [{"name": fake_name}]}
        clt.method_get = Mock(return_value=({}, ret_body))
        ret = clt.list()
        self.assertEqual(len(ret), 1)

    def test_manager_list_all(self):
        clt = self.client
        mgr = clt._manager
        fake_name = utils.random_unicode()
        ret_body = {"domains": [{"name": fake_name}]}
        uri_string_next = utils.random_unicode()
        next_uri = "%s/domains/%s" % (example_uri, uri_string_next)
        mgr.count = 0

        def mock_get(uri):
            if mgr.count:
                return ({}, ret_body)
            mgr.count += 1
            ret = {"totalEntries": 2,
                    "links": [
                        {"href": next_uri,
                         "rel": "next"}]}
            ret.update(ret_body)
            return ({}, ret)

        clt.method_get = Mock(wraps=mock_get)
        ret = mgr._list(example_uri, list_all=True)
        self.assertEqual(len(ret), 2)

    def test_list_previous_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["domain"]["prev_uri"] = example_uri
        mgr._list = Mock()
        clt.list_previous_page()
        mgr._list.assert_called_once_with(example_uri)

    def test_list_previous_page_fail(self):
        clt = self.client
        mgr = clt._manager
        self.assertRaises(exc.NoMoreResults, clt.list_previous_page)

    def test_list_next_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["domain"]["next_uri"] = example_uri
        mgr._list = Mock()
        clt.list_next_page()
        mgr._list.assert_called_once_with(example_uri)

    def test_list_next_page_fail(self):
        clt = self.client
        mgr = clt._manager
        self.assertRaises(exc.NoMoreResults, clt.list_next_page)

    def test_list_subdomains_previous_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["subdomain"]["prev_uri"] = example_uri
        mgr._list_subdomains = Mock()
        clt.list_subdomains_previous_page()
        mgr._list_subdomains.assert_called_once_with(example_uri)

    def test_list_subdomains_previous_page_fail(self):
        clt = self.client
        mgr = clt._manager
        self.assertRaises(exc.NoMoreResults, clt.list_subdomains_previous_page)

    def test_list_subdomains_next_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["subdomain"]["next_uri"] = example_uri
        mgr._list_subdomains = Mock()
        clt.list_subdomains_next_page()
        mgr._list_subdomains.assert_called_once_with(example_uri)

    def test_list_subdomains_next_page_fail(self):
        clt = self.client
        mgr = clt._manager
        self.assertRaises(exc.NoMoreResults, clt.list_subdomains_next_page)

    def test_list_records_previous_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["record"]["prev_uri"] = example_uri
        mgr._list_records = Mock()
        clt.list_records_previous_page()
        mgr._list_records.assert_called_once_with(example_uri)

    def test_list_records_previous_page_fail(self):
        clt = self.client
        mgr = clt._manager
        self.assertRaises(exc.NoMoreResults, clt.list_records_previous_page)

    def test_list_records_next_page(self):
        clt = self.client
        mgr = clt._manager
        mgr._paging["record"]["next_uri"] = example_uri
        mgr._list_records = Mock