import unittest
from mock import MagicMock
from collections import namedtuple

from psychic_disco.rest_resource import RestResource
from psychic_disco.rest_api import RestApi


class TestRestResource(unittest.TestCase):
    def test_rest_resource_not_exists(self):
        resource = RestResource('/dummies')
        self.assertFalse(resource.exists_in_aws)

    def test_rest_resource_exists(self):
        api = RestApi.find("dummy-manager")
        resource = RestResource('/dummies')
        resource.aws_id = "123resourceid"
        resource.api = api
        self.assertTrue(resource.exists_in_aws)

    def test_rest_resource_fetch_from_aws(self):
        api = RestApi.find("dummy-manager")
        resource = RestResource('/dummies')
        resource.aws_id = "123resourceid"
        resource.api = api

        self.assertEqual(0, len(resource.methods))
        resource.fetch_from_aws()
        self.assertEqual(1, len(resource.methods))

    def test_rest_resource_path_part(self):
        api = RestApi.find("dummy-manager")
        resource = RestResource('/dummies/by_name')
        resource.api = api
        self.assertEqual(resource.path_part, "by_name")

    def test_root_path_part(self):
        api = RestApi.find("dummy-manager")
        resource = RestResource('/')
        resource.api = api
        self.assertEqual(resource.path_part, "/")

    def test_exists_in_aws(self):
        resource = RestResource('/dummies/by_name')
        self.assertFalse(resource.exists_in_aws)
        resource.aws_id = 5
        resource.api = MagicMock()
        self.assertTrue(resource.exists_in_aws)

    def test_new_declare_method(self):
        r = RestResource('/dummies/by_name')
        m = r.declare_method('post')
        self.assertEqual(m.api, r.api)

    def test_redeclare_method(self):
        r = RestResource('/dummies/by_name')
        m1 = r.declare_method('post')
        m2 = r.declare_method('post')
        self.assertEqual(m1, m2)

    def test_declare_route(self):
        MockLambda = namedtuple('MockLambda', ['proper_name'])
        lf = MockLambda('mock.lambda')
        r = RestResource('/dummies/by_name')
        r.declare_route('POST', lf)
        self.assertEqual(r.methods['POST'].lambda_name, 'mock.lambda')

    def test_parent_of_root(self):
        r = RestResource('/')
        self.assertIsNone(r.parent)

    def test_parent(self):
        r = RestResource('/dummies/by_name')
        r.api = RestApi.find("dummy-manager")
        self.assertEqual(r.parent.path_part, '/dummies')

    def test_create_resource(self):
        r = RestResource('/dummies/by_name')
        r.api = RestApi.find("dummy-manager")
        r.api.aws_id = 6
        MockConsole = namedtuple('MockConsole', ['create_resource'])
        r.console = MockConsole
        r.console.create_resource = MagicMock(return_value=5)
        self.assertEqual(r._create_resource(), 5)
        r.console.create_resource.assert_called_with(
                restApiId=6,
                parentId='123resourceid',
                pathPart='by_name'
                )

    def test_deploy(self):
        r = RestResource('/dummies/by_name')
        r.api = RestApi.find("dummy-manager")
        MockDeployable = namedtuple('MockDeployable', ['deploy'])
        r.parent.deploy = MagicMock()
        r.methods['POST'] = MockDeployable(deploy=MagicMock())
        r._create_resource = MagicMock(return_value={'id': 5})

        r.deploy()

        r.parent.deploy.assert_called_with()
        r.methods['POST'].deploy.assert_called_with()
        r._create_resource.assert_called_with()
        self.assertEqual(r.aws_id, 5)
