#    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.

import yaml

from heat_integrationtests.common import test


class DefaultParametersTest(test.HeatIntegrationTest):

    template = '''
heat_template_version: 2013-05-23
parameters:
  length:
    type: string
    default: 40
resources:
  random1:
    type: nested_random.yaml
  random2:
    type: OS::Heat::RandomString
    properties:
      length: {get_param: length}
outputs:
  random1:
    value: {get_attr: [random1, random1_value]}
  random2:
    value: {get_resource: random2}
'''
    nested_template = '''
heat_template_version: 2013-05-23
parameters:
  length:
    type: string
    default: 50
resources:
  random1:
    type: OS::Heat::RandomString
    properties:
      length: {get_param: length}
outputs:
  random1_value:
    value: {get_resource: random1}
'''

    scenarios = [
        ('none', dict(param=None, default=None, temp_def=True,
                      expect1=50, expect2=40)),
        ('default', dict(param=None, default=12, temp_def=True,
                         expect1=12, expect2=12)),
        ('both', dict(param=15, default=12, temp_def=True,
                      expect1=12, expect2=15)),
        ('no_temp_default', dict(param=None, default=12, temp_def=False,
                                 expect1=12, expect2=12)),
    ]

    def setUp(self):
        super(DefaultParametersTest, self).setUp()
        self.client = self.orchestration_client

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

        env = {'parameters': {}, 'parameter_defaults': {}}
        if self.param:
            env['parameters'] = {'length': self.param}
        if self.default:
            env['parameter_defaults'] = {'length': self.default}

        if not self.temp_def:
            # remove the default from the parameter in the nested template.
            ntempl = yaml.load(self.nested_template)
            del ntempl['parameters']['length']['default']
            nested_template = yaml.dump(ntempl)
        else:
            nested_template = self.nested_template

        self.client.stacks.create(
            stack_name=stack_name,
            template=self.template,
            files={'nested_random.yaml': nested_template},
            disable_rollback=True,
            parameters={},
            environment=env
        )
        self.addCleanup(self.client.stacks.delete, stack_name)

        stack = self.client.stacks.get(stack_name)
        stack_identifier = '%s/%s' % (stack_name, stack.id)

        self._wait_for_stack_status(stack_identifier, 'CREATE_COMPLETE')

        stack = self.client.stacks.get(stack_name)
        for out in stack.outputs:
            if out['output_key'] == 'random1':
                self.assertEqual(self.expect1, len(out['output_value']))
            if out['output_key'] == 'random2':
                self.assertEqual(self.expect2, len(out['output_value']))
