from unittest import TestCase
from mock import patch, Mock

from samcli.commands.local.start_lambda.cli import do_cli as start_lambda_cli
from samcli.commands.local.cli_common.user_exceptions import UserException
from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException
from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError


class TestCli(TestCase):

    def setUp(self):
        self.template = "template"
        self.env_vars = "env-vars"
        self.debug_port = 123
        self.debug_args = "args"
        self.debugger_path = "/test/path"
        self.docker_volume_basedir = "basedir"
        self.docker_network = "network"
        self.log_file = "logfile"
        self.skip_pull_image = True
        self.profile = "profile"
        self.region = "region"
        self.parameter_overrides = {}

        self.host = "host"
        self.port = 123

    @patch("samcli.commands.local.start_lambda.cli.InvokeContext")
    @patch("samcli.commands.local.start_lambda.cli.LocalLambdaService")
    def test_cli_must_setup_context_and_start_service(self, local_lambda_service_mock,
                                                      invoke_context_mock):
        # Mock the __enter__ method to return a object inside a context manager
        context_mock = Mock()
        invoke_context_mock.return_value.__enter__.return_value = context_mock

        service_mock = Mock()
        local_lambda_service_mock.return_value = service_mock

        self.call_cli()

        invoke_context_mock.assert_called_with(template_file=self.template,
                                               function_identifier=None,
                                               env_vars_file=self.env_vars,
                                               docker_volume_basedir=self.docker_volume_basedir,
                                               docker_network=self.docker_network,
                                               log_file=self.log_file,
                                               skip_pull_image=self.skip_pull_image,
                                               aws_profile=self.profile,
                                               debug_port=self.debug_port,
                                               debug_args=self.debug_args,
                                               debugger_path=self.debugger_path,
                                               aws_region=self.region,
                                               parameter_overrides=self.parameter_overrides)

        local_lambda_service_mock.assert_called_with(lambda_invoke_context=context_mock,
                                                     port=self.port,
                                                     host=self.host)

        service_mock.start.assert_called_with()

    @patch("samcli.commands.local.start_lambda.cli.InvokeContext")
    def test_must_raise_user_exception_on_invalid_sam_template(self, invoke_context_mock):
        invoke_context_mock.side_effect = InvalidSamDocumentException("bad template")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "bad template"
        self.assertEquals(msg, expected)

    @patch("samcli.commands.local.start_lambda.cli.InvokeContext")
    def test_must_raise_user_exception_on_invalid_env_vars(self, invoke_context_mock):
        invoke_context_mock.side_effect = OverridesNotWellDefinedError("bad env vars")

        with self.assertRaises(UserException) as context:
            self.call_cli()

        msg = str(context.exception)
        expected = "bad env vars"
        self.assertEquals(msg, expected)

    def call_cli(self):
        start_lambda_cli(ctx=None,
                         host=self.host,
                         port=self.port,
                         template=self.template,
                         env_vars=self.env_vars,
                         debug_port=self.debug_port,
                         debug_args=self.debug_args,
                         debugger_path=self.debugger_path,
                         docker_volume_basedir=self.docker_volume_basedir,
                         docker_network=self.docker_network,
                         log_file=self.log_file,
                         skip_pull_image=self.skip_pull_image,
                         profile=self.profile,
                         region=self.region,
                         parameter_overrides=self.parameter_overrides)

[((29, 5, 29, 66), 'mock.patch', 'patch', ({(29, 11, 29, 65): '"""samcli.commands.local.start_lambda.cli.InvokeContext"""'}, {}), "('samcli.commands.local.start_lambda.cli.InvokeContext')", False, 'from mock import patch, Mock\n'), ((30, 5, 30, 71), 'mock.patch', 'patch', ({(30, 11, 30, 70): '"""samcli.commands.local.start_lambda.cli.LocalLambdaService"""'}, {}), "('samcli.commands.local.start_lambda.cli.LocalLambdaService')", False, 'from mock import patch, Mock\n'), ((62, 5, 62, 66), 'mock.patch', 'patch', ({(62, 11, 62, 65): '"""samcli.commands.local.start_lambda.cli.InvokeContext"""'}, {}), "('samcli.commands.local.start_lambda.cli.InvokeContext')", False, 'from mock import patch, Mock\n'), ((73, 5, 73, 66), 'mock.patch', 'patch', ({(73, 11, 73, 65): '"""samcli.commands.local.start_lambda.cli.InvokeContext"""'}, {}), "('samcli.commands.local.start_lambda.cli.InvokeContext')", False, 'from mock import patch, Mock\n'), ((34, 23, 34, 29), 'mock.Mock', 'Mock', ({}, {}), '()', False, 'from mock import patch, Mock\n'), ((37, 23, 37, 29), 'mock.Mock', 'Mock', ({}, {}), '()', False, 'from mock import patch, Mock\n'), ((64, 42, 64, 85), 'samcli.commands.validate.lib.exceptions.InvalidSamDocumentException', 'InvalidSamDocumentException', ({(64, 70, 64, 84): '"""bad template"""'}, {}), "('bad template')", False, 'from samcli.commands.validate.lib.exceptions import InvalidSamDocumentException\n'), ((75, 42, 75, 86), 'samcli.commands.local.lib.exceptions.OverridesNotWellDefinedError', 'OverridesNotWellDefinedError', ({(75, 71, 75, 85): '"""bad env vars"""'}, {}), "('bad env vars')", False, 'from samcli.commands.local.lib.exceptions import OverridesNotWellDefinedError\n'), ((85, 8, 99, 70), 'samcli.commands.local.start_lambda.cli.do_cli', 'start_lambda_cli', (), '', True, 'from samcli.commands.local.start_lambda.cli import do_cli as start_lambda_cli\n')]