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

from mock import patch, Mock
from . import mkfuture

from tornado import gen
from tornado.testing import AsyncTestCase, gen_test
from tornadoalf.manager import TokenManager, TokenError
from tornadoalf.client import Client


class TestClient(AsyncTestCase):

    end_point = 'http://endpoint/token'
    resource_url = 'http://api/some/resource'

    def test_Client_should_have_a_variable_with_a_token_manager_class(self):
        self.assertEquals(Client.token_manager_class, TokenManager)

    def test_token_manager_object_should_be_an_instance_of_token_manager_class(self):  # noqa = E501
        client = Client(token_endpoint=self.end_point,
                        client_id='client-id', client_secret='client_secret')

        self.assertTrue(
            isinstance(client._token_manager, client.token_manager_class)
        )

    @gen_test
    @patch('tornadoalf.client.TokenManager')
    def test_should_return_a_good_request(self, Manager):
        manager = self._fake_manager(Manager, has_token=False)

        with patch('tornadoalf.client.Client._authorized_fetch') as _authorized_fetch:  # noqa = E501
            _authorized_fetch.return_value = mkfuture(Mock(code=200))

            response = yield self._request(Manager)
            self.assertEqual(response.code, 200)
            self.assertEqual(_authorized_fetch.call_count, 1)
            self.assertEqual(manager.reset_token.call_count, 0)

    @gen_test
    @patch('tornadoalf.client.TokenManager')
    def test_should_return_a_bad_request(self, Manager):
        manager = self._fake_manager(Manager, has_token=False)

        with patch('tornadoalf.client.Client._authorized_fetch') as _authorized_fetch:  # noqa = E501
            _authorized_fetch.return_value = mkfuture(Mock(code=400))

            response = yield self._request(Manager)
            self.assertEqual(response.code, 400)
            self.assertEqual(_authorized_fetch.call_count, 1)
            self.assertEqual(manager.reset_token.call_count, 0)

    @gen_test
    @patch('tornadoalf.client.TokenManager')
    def test_should_retry_a_bad_token_request_once(self, Manager):
        self._fake_manager(Manager, has_token=False)

        with patch('tornadoalf.client.Client._authorized_fetch') as _authorized_fetch:  # noqa = E501
            _authorized_fetch.return_value = mkfuture(Mock(code=401))

            response = yield self._request(Manager)
            self.assertEqual(response.code, 401)
            self.assertEqual(_authorized_fetch.call_count, 2)

    @gen_test
    @patch('tornadoalf.client.TokenManager')
    def test_should_reset_token_when_token_fails(self, Manager):
        manager = self._fake_manager(Manager, has_token=False)

        with patch('tornadoalf.client.Client._authorized_fetch') as _authorized_fetch:  # noqa = E501
            _authorized_fetch.return_value = mkfuture(Mock(code=401))

            response = yield self._request(Manager)
            self.assertEqual(response.code, 401)
            self.assertEqual(manager.reset_token.call_count, 1)

    @gen_test
    @patch('tornadoalf.client.TokenManager')
    def test_should_reset_token_when_gets_a_token_error(self, Manager):
        manager = self._fake_manager(Manager, has_token=False)

        with patch('tornadoalf.client.Client._authorized_fetch') as _authorized_fetch:  # noqa = E501
            _authorized_fetch.side_effect = TokenError('boom', 'boom')

            try:
                yield self._request(Manager)
            except TokenError as e:
                if hasattr(e, 'message'):
                    self.assertEqual(e.message, 'boom')
                elif hasattr(e, 'response'):
                    self.assertEqual(e.response, 'boom')
                else:
                    assert False, 'Should not have got this far'
                self.assertEqual(_authorized_fetch.call_count, 1)
                self.assertEqual(manager.reset_token.call_count, 1)
            else:
                assert False, 'Should not have got this far'

    @gen.coroutine
    def _request(self, manager):
        class ClientTest(Client):
            token_manager_class = manager

        client = ClientTest(
            token_endpoint=self.end_point,
            client_id='client_id',
            client_secret='client_secret')

        result = yield client.fetch(self.resource_url, method='GET')
        raise gen.Return(result)

    def _fake_manager(self, Manager, has_token=True,
                      access_token='', code=200):
        if not isinstance(access_token, list):
            access_token = [access_token]

        access_token.reverse()

        manager = Mock()
        manager._has_token.return_value = has_token
        manager.get_token.return_value = mkfuture(access_token[0])
        manager.request_token.return_value = mkfuture(Mock(
            code=code,
            error=(code == 200 and None or Exception('error'))
        ))

        Manager.return_value = manager

        return manager

@@ -522,30 +522,24 @@
 ef test_
-token_
 manager_
 object_s
@@ -534,15 +534,8 @@
 ger_
-object_
 shou
@@ -545,21 +545,8 @@
 be_a
-n_instance_of
 _tok
@@ -568,31 +568,16 @@
 s(self):
-  # noqa = E501
 %0A       
@@ -1054,32 +1054,53 @@
 ized_fetch') as 
+(%0A                   
 _authorized_fetc
@@ -1100,32 +1100,19 @@
 ed_fetch
-:  # noqa = E501
+):%0A
 %0A       
@@ -1170,25 +1170,24 @@
 (code=200))%0A
-%0A
             
@@ -1642,32 +1642,53 @@
 ized_fetch') as 
+(%0A                   
 _authorized_fetc
@@ -1688,32 +1688,19 @@
 ed_fetch
-:  # noqa = E501
+):%0A
 %0A       
@@ -1762,17 +1762,16 @@
 e=400))%0A
-%0A
         
@@ -2230,32 +2230,53 @@
 ized_fetch') as 
+(%0A                   
 _authorized_fetc
@@ -2276,32 +2276,19 @@
 ed_fetch
-:  # noqa = E501
+):%0A
 %0A       
@@ -2342,33 +2342,32 @@
 Mock(code=401))%0A
-%0A
             resp
@@ -2762,32 +2762,53 @@
 ized_fetch') as 
+(%0A                   
 _authorized_fetc
@@ -2808,32 +2808,19 @@
 ed_fetch
-:  # noqa = E501
+):%0A
 %0A       
@@ -2882,17 +2882,16 @@
 e=401))%0A
-%0A
         
@@ -3311,16 +3311,37 @@
 ch') as 
+(%0A                   
 _authori
@@ -3353,24 +3353,11 @@
 etch
-:  # noqa = E501
+):%0A
 %0A   
@@ -3424,17 +3424,16 @@
 'boom')%0A
-%0A
         

Remove noqa = E501