# Copyright 2015 OpenStack Foundation.
# All Rights Reserved
#
#    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 networking_plumgrid._i18n import _
from neutronclient.common import extension
from neutronclient.common import utils
from oslo_serialization import jsonutils

INTERFACE_DELIMITER = ";"
SEGMENTATION_ID_DELIMITER = "#"
INTERFACE_SEG_ID_DELIMITER = "|"


def _format_devices(l2_gateway):
    try:
        return '\n'.join([jsonutils.dumps(gateway) for gateway in
                          l2_gateway['devices']])
    except (TypeError, KeyError):
        return ''


class L2Gateway(extension.NeutronClientExtension):
    resource = 'l2_gateway'
    resource_plural = 'l2_gateways'
    path = 'l2-gateways'
    object_path = '/%s' % path
    resource_path = '/%s/%%s' % path
    versions = ['2.0']


def get_interface(interfaces):
    interface_dict = []
    for interface in interfaces:
        if INTERFACE_SEG_ID_DELIMITER in interface:
            int_name = interface.split(INTERFACE_SEG_ID_DELIMITER)[0]
            segid = interface.split(INTERFACE_SEG_ID_DELIMITER)[1]
            if SEGMENTATION_ID_DELIMITER in segid:
                segid = segid.split(SEGMENTATION_ID_DELIMITER)
            else:
                segid = [segid]
            interface_detail = {'name': int_name, 'segmentation_id': segid}
        else:
            interface_detail = {'name': interface}
        interface_dict.append(interface_detail)
    return interface_dict


def add_known_arguments(self, parser):
    parser.add_argument(
            '--vtep_ifc', dest='vtep_ifc',
            help=_('VTEP interface for logical gateway.'))
    parser.add_argument(
            '--vtep_ip', dest='vtep_ip',
            help=_('VTEP IP for logical gateway.'))
    parser.add_argument(
        '--device',
        metavar='name=name,device_ip=ip,interface_names=INTERFACE-DETAILS',
        action='append', dest='devices', type=utils.str2dict,
        help=_('Device name and Interface-names of l2gateway. '
               'Device ip of switch '
               'INTERFACE-DETAILS is of form '
               '\"<interface_name1>'
               '|<seg_id1>\" '
               '(--device option can be repeated)'))


def args2body(self, parsed_args):
        if parsed_args.devices:
            devices = parsed_args.devices
            interfaces = []
        else:
            devices = []
        device_dict = []
        for device in devices:
            if 'interface_names' in device.keys():
                interface = device['interface_names']
                if INTERFACE_DELIMITER in interface:
                    interface_dict = interface.split(INTERFACE_DELIMITER)
                    interfaces = get_interface(interface_dict)
                else:
                    interfaces = get_interface([interface])
            if 'name' in device.keys():
                dvc = {'device_name': device['name'],
                       'interfaces': interfaces}
            else:
                dvc = {'interfaces': interfaces}
            if 'device_ip' in device.keys():
                dvc.update({'device_ip': device['device_ip']})
            device_dict.append(dvc)
        if parsed_args.name and parsed_args.vtep_ifc and parsed_args.vtep_ip:
            l2gw_name = parsed_args.name
            vtep_ifc = parsed_args.vtep_ifc
            vtep_ip = parsed_args.vtep_ip
            body = {'l2_gateway': {'name': l2gw_name,
                                   'vtep_ifc': vtep_ifc,
                                   'vtep_ip': vtep_ip,
                                   'devices': device_dict}, }
        else:
            body = {'l2_gateway': {'devices': device_dict}, }
        return body


class L2GatewayCreate(extension.ClientExtensionCreate, L2Gateway):
    """Create l2gateway information."""

    shell_command = 'l2-gateway-create'

    def add_known_arguments(self, parser):
        parser.add_argument(
            'name', metavar='<GATEWAY-NAME>',
            help=_('Descriptive name for logical gateway.'))
        add_known_arguments(self, parser)

    def args2body(self, parsed_args):
        body = args2body(self, parsed_args)
        if parsed_args.tenant_id:
            body['l2_gateway']['tenant_id'] = parsed_args.tenant_id
        return body


class L2GatewayList(extension.ClientExtensionList, L2Gateway):
    """List l2gateway that belongs to a given tenant."""

    shell_command = 'l2-gateway-list'
    _formatters = {'devices': _format_devices, }
    list_columns = ['id', 'name', 'vtep_ifc', 'vtep_ip', 'devices']
    pagination_support = True
    sorting_support = True


class L2GatewayShow(extension.ClientExtensionShow, L2Gateway):
    """Show information of a given l2gateway."""

    shell_command = 'l2-gateway-show'


class L2GatewayDelete(extension.ClientExtensionDelete, L2Gateway):
    """Delete a given l2gateway."""

    shell_command = 'l2-gateway-delete'


class L2GatewayUpdate(extension.ClientExtensionUpdate, L2Gateway):
    """Update a given l2gateway."""

    shell_command = 'l2-gateway-update'

    def add_known_arguments(self, parser):
        parser.add_argument(
            '--name', metavar='name',
            help=_('Descriptive name for logical gateway.'))
        add_known_arguments(self, parser)

    def args2body(self, parsed_args):
        if parsed_args.devices:
            body = args2body(self, parsed_args)
        else:
            body = {'l2_gateway': {'name': parsed_args.name}}
        return body
