#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from heat_integrationtests.common import test
from heatclient import exc
import six


class StackPreviewTest(test.HeatIntegrationTest):
    template = '''
heat_template_version: 2015-04-30
parameters:
  incomming:
    type: string
resources:
  one:
    type: OS::Heat::TestResource
    properties:
      value: fred
  two:
    type: OS::Heat::TestResource
    properties:
      value: {get_param: incomming}
    depends_on: one
outputs:
  main_out:
    value: {get_attr: [two, output]}
    '''
    env = '''
parameters:
  incomming: abc
    '''

    def setUp(self):
        super(StackPreviewTest, self).setUp()
        self.client = self.orchestration_client
        self.project_id = self.identity_client.auth_ref.project_id

    def _assert_resource(self, res, stack_name):
        self.assertEqual(stack_name, res['stack_name'])
        self.assertEqual('INIT', res['resource_action'])
        self.assertEqual('COMPLETE', res['resource_status'])
        for field in ('resource_status_reason', 'physical_resource_id',
                      'description'):
            self.assertIn(field, res)
            self.assertEqual('', res[field])
        for field in ('creation_time', 'updated_time'):
            self.assertIn(field, res)
            self.assertIsNotNone(res[field])
        self.assertIn('output', res['attributes'])

        # resource_identity
        self.assertEqual(stack_name,
                         res['resource_identity']['stack_name'])
        self.assertEqual('None', res['resource_identity']['stack_id'])
        self.assertEqual(self.project_id,
                         res['resource_identity']['tenant'])
        self.assertEqual('/resources/%s' % res['resource_name'],
                         res['resource_identity']['path'])
        # stack_identity
        self.assertEqual(stack_name,
                         res['stack_identity']['stack_name'])
        self.assertEqual('None', res['stack_identity']['stack_id'])
        self.assertEqual(self.project_id,
                         res['stack_identity']['tenant'])
        self.assertEqual('', res['stack_identity']['path'])

    def _assert_results(self, result, stack_name):
        # global stuff.
        self.assertEqual(stack_name, result['stack_name'])
        self.assertTrue(result['disable_rollback'])
        self.assertEqual('None', result['id'])
        self.assertIsNone(result['parent'])
        self.assertEqual('No description', result['template_description'])

        # parameters
        self.assertEqual('None', result['parameters']['OS::stack_id'])
        self.assertEqual(stack_name, result['parameters']['OS::stack_name'])
        self.assertEqual('abc', result['parameters']['incomming'])

    def test_basic_pass(self):
        stack_name = self._stack_rand_name()
        result = self.client.stacks.preview(
            template=self.template,
            stack_name=stack_name,
            disable_rollback=True,
            environment=self.env).to_dict()

        self._assert_results(result, stack_name)
        for res in result['resources']:
            self._assert_resource(res, stack_name)
            self.assertEqual('OS::Heat::TestResource',
                             res['resource_type'])

            # common properties
            self.assertEqual(False, res['properties']['fail'])
            self.assertEqual(0, res['properties']['wait_secs'])
            self.assertEqual(False, res['properties']['update_replace'])

            if res['resource_name'] == 'one':
                self.assertEqual('fred', res['properties']['value'])
                self.assertEqual(['two'], res['required_by'])
            if res['resource_name'] == 'two':
                self.assertEqual('abc', res['properties']['value'])
                self.assertEqual([], res['required_by'])

    def test_basic_fail(self):
        stack_name = self._stack_rand_name()

        # break the template so it fails validation.
        wont_work = self.template.replace('get_param: incomming',
                                          'get_param: missing')
        excp = self.assertRaises(exc.HTTPBadRequest,
                                 self.client.stacks.preview,
                                 template=wont_work,
                                 stack_name=stack_name,
                                 disable_rollback=True,
                                 environment=self.env)

        self.assertIn('Property error: : resources.two.properties.value: '
                      ': The Parameter (missing) was not provided.',
                      six.text_type(excp))

    def test_nested_pass(self):
        """Nested stacks need to recurse down the stacks."""
        main_template = '''
heat_template_version: 2015-04-30
parameters:
  incomming:
    type: string
resources:
  main:
    type: nested.yaml
    properties:
      value: {get_param: incomming}
outputs:
  main_out:
    value: {get_attr: [main, output]}
    '''
        nested_template = '''
heat_template_version: 2015-04-30
parameters:
  value:
    type: string
resources:
  nested:
    type: OS::Heat::TestResource
    properties:
      value: {get_param: value}
outputs:
  output:
    value: {get_attr: [nested, output]}
'''
        stack_name = self._stack_rand_name()
        result = self.client.stacks.preview(
            disable_rollback=True,
            stack_name=stack_name,
            template=main_template,
            files={'nested.yaml': nested_template},
            environment=self.env).to_dict()

        self._assert_results(result, stack_name)

        # nested resources return a list of their resources.
        res = result['resources'][0][0]
        nested_stack_name = '%s-%s' % (stack_name,
                                       res['parent_resource'])

        self._assert_resource(res, nested_stack_name)
        self.assertEqual('OS::Heat::TestResource',
                         res['resource_type'])

        self.assertEqual(False, res['properties']['fail'])
        self.assertEqual(0, res['properties']['wait_secs'])
        self.assertEqual(False, res['properties']['update_replace'])

        self.assertEqual('abc', res['properties']['value'])
        self.assertEqual([], res['required_by'])
