#
# 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 toscaparser.common.exception import InvalidPropertyValueError
from translator.hot.syntax.hot_resource import HotResource

# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNetwork'


class ToscaNetwork(HotResource):
    '''Translate TOSCA node type tosca.nodes.network.Network.'''

    toscatype = 'tosca.nodes.network.Network'
    SUBNET_SUFFIX = '_subnet'
    NETWORK_PROPS = ['network_name', 'network_id', 'segmentation_id']
    SUBNET_PROPS = ['ip_version', 'cidr', 'start_ip', 'end_ip', 'gateway_ip']

    existing_resource_id = None

    def __init__(self, nodetemplate, csar_dir=None):
        super(ToscaNetwork, self).__init__(nodetemplate,
                                           type='OS::Neutron::Net',
                                           csar_dir=csar_dir)
        pass

    def handle_properties(self):
        tosca_props = self.get_tosca_props()

        net_props = {}
        for key, value in tosca_props.items():
            if key in self.NETWORK_PROPS:
                if key == 'network_name':
                    # If CIDR is specified network_name should
                    # be used as the name for the new network.
                    if 'cidr' in tosca_props.keys():
                        net_props['name'] = value
                    # If CIDR is not specified network_name will be used
                    # to lookup existing network. If network_id is specified
                    # together with network_name then network_id should be
                    # used to lookup the network instead
                    elif 'network_id' not in tosca_props.keys():
                        self.hide_resource = True
                        self.existing_resource_id = value
                        break
                elif key == 'network_id':
                    self.hide_resource = True
                    self.existing_resource_id = value
                    break
                elif key == 'segmentation_id':
                    # Hardcode to vxlan for now until we add the network type
                    # and physical network to the spec.
                    net_props['value_specs'] = {'provider:segmentation_id':
                                                value, 'provider:network_type':
                                                'vxlan'}
        self.properties = net_props

    def handle_expansion(self):
        # If the network resource should not be output (they are hidden),
        # there is no need to generate subnet resource
        if self.hide_resource:
            return

        tosca_props = self.get_tosca_props()

        subnet_props = {}

        ip_pool_start = None
        ip_pool_end = None

        for key, value in tosca_props.items():
            if key in self.SUBNET_PROPS:
                if key == 'start_ip':
                    ip_pool_start = value
                elif key == 'end_ip':
                    ip_pool_end = value
                elif key == 'dhcp_enabled':
                    subnet_props['enable_dhcp'] = value
                else:
                    subnet_props[key] = value

        if 'network_id' in tosca_props:
            subnet_props['network'] = tosca_props['network_id']
        else:
            subnet_props['network'] = '{ get_resource: %s }' % (self.name)

        # Handle allocation pools
        # Do this only if both start_ip and end_ip are provided
        # If one of them is missing throw an exception.
        if ip_pool_start and ip_pool_end:
            allocation_pool = {}
            allocation_pool['start'] = ip_pool_start
            allocation_pool['end'] = ip_pool_end
            allocation_pools = [allocation_pool]
            subnet_props['allocation_pools'] = allocation_pools
        elif ip_pool_start:
            raise InvalidPropertyValueError(what=_('start_ip'))
        elif ip_pool_end:
            raise InvalidPropertyValueError(what=_('end_ip'))

        subnet_resource_name = self.name + self.SUBNET_SUFFIX

        hot_resources = [HotResource(self.nodetemplate,
                                     type='OS::Neutron::Subnet',
                                     name=subnet_resource_name,
                                     properties=subnet_props)]
        return hot_resources
