#
#    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.common.i18n import _
from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine import support


class KeystoneProject(resource.Resource):
    '''
    Heat Template Resource for Keystone Project.

    heat_template_version: 2013-05-23

    description: Sample Keystone Project template

    parameters:
      project_name:
        type: string
        description: Keystone project name
      project_description:
        type: string
        description: Keystone project description
      project_enabled:
        type: boolean
        description: Keystone project is enabled or disabled
      project_domain:
        type: string
        description: Keystone project domain name or id

    resources:
      admin_project:
        type: OS::Keystone::Project
        properties:
          name: {get_param: project_name}
          domain: {get_param: project_domain}
          description: {get_param: project_description}
          enabled: {get_param: project_enabled}

    '''

    support_status = support.SupportStatus(
        version='2015.1',
        message=_('Supported versions: keystone v3'))

    PROPERTIES = (
        NAME, DOMAIN, DESCRIPTION, ENABLED
    ) = (
        'name', 'domain', 'description', 'enabled'
    )

    properties_schema = {
        NAME: properties.Schema(
            properties.Schema.STRING,
            _('Name of keystone project.'),
            update_allowed=True
        ),
        DOMAIN: properties.Schema(
            properties.Schema.STRING,
            _('Name or id of keystone domain.'),
            default='default',
            update_allowed=True,
            constraints=[constraints.CustomConstraint('keystone.domain')]
        ),
        DESCRIPTION: properties.Schema(
            properties.Schema.STRING,
            _('Description of keystone project.'),
            default='',
            update_allowed=True
        ),
        ENABLED: properties.Schema(
            properties.Schema.BOOLEAN,
            _('This project is enabled or disabled.'),
            default=True,
            update_allowed=True
        )
    }

    def _create_project(self,
                        project_name,
                        description,
                        domain,
                        enabled):
        domain = (self.client_plugin('keystone').
                  get_domain_id(domain))

        return self.keystone().client.projects.create(
            name=project_name,
            domain=domain,
            description=description,
            enabled=enabled)

    def _delete_project(self, project_id):
        return self.keystone().client.projects.delete(project_id)

    def _update_project(self,
                        project_id,
                        domain,
                        new_name=None,
                        new_description=None,
                        enabled=None):
        values = dict()

        if new_name is not None:
            values['name'] = new_name
        if new_description is not None:
            values['description'] = new_description
        if enabled is not None:
            values['enabled'] = enabled

        values['project'] = project_id
        domain = (self.client_plugin('keystone').
                  get_domain_id(domain))

        values['domain'] = domain

        return self.keystone().client.projects.update(**values)

    def handle_create(self):
        project_name = (self.properties.get(self.NAME) or
                        self.physical_resource_name())
        description = self.properties.get(self.DESCRIPTION)
        domain = self.properties.get(self.DOMAIN)
        enabled = self.properties.get(self.ENABLED)

        project = self._create_project(
            project_name=project_name,
            description=description,
            domain=domain,
            enabled=enabled
        )

        self.resource_id_set(project.id)

    def handle_update(self,
                      json_snippet=None,
                      tmpl_diff=None,
                      prop_diff=None):
        name = prop_diff.get(self.NAME) or self.physical_resource_name()
        description = prop_diff.get(self.DESCRIPTION)
        enabled = prop_diff.get(self.ENABLED)
        domain = (prop_diff.get(self.DOMAIN) or
                  self._stored_properties_data.get(self.DOMAIN))

        self._update_project(
            project_id=self.resource_id,
            domain=domain,
            new_name=name,
            new_description=description,
            enabled=enabled
        )

    def handle_delete(self):
        if self.resource_id is not None:
            try:
                self._delete_project(project_id=self.resource_id)
            except Exception as ex:
                self.client_plugin('keystone').ignore_not_found(ex)


def resource_mapping():
    return {
        'OS::Keystone::Project': KeystoneProject
    }
