/*
 * Copyright 2017-present Open Networking Laboratory
 *
 * 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.
 */
package org.onosproject.drivers.lisp.extensions;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.lisp.ctl.ExtensionMappingAddressInterpreter;
import org.onosproject.lisp.msg.types.LispAfiAddress;
import org.onosproject.lisp.msg.types.LispDistinguishedNameAddress;
import org.onosproject.lisp.msg.types.LispIpv4Address;
import org.onosproject.lisp.msg.types.LispIpv6Address;
import org.onosproject.lisp.msg.types.LispMacAddress;
import org.onosproject.lisp.msg.types.lcaf.LispAppDataLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispAsLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispGeoCoordinateLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispListLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispMulticastLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispNatLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispNonceLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispSegmentLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispSourceDestLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispTeLcafAddress;
import org.onosproject.lisp.msg.types.lcaf.LispTeRecord;
import org.onosproject.mapping.addresses.ExtensionMappingAddress;
import org.onosproject.mapping.addresses.ExtensionMappingAddressResolver;
import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
import org.onosproject.mapping.addresses.IPMappingAddress;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.addresses.MappingAddresses;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

import static org.onosproject.mapping.addresses.ExtensionMappingAddressType.ExtensionMappingAddressTypes.*;
/**
 * Interpreter for mapping address extension.
 */
public class LispExtensionMappingAddressInterpreter extends AbstractHandlerBehaviour
        implements ExtensionMappingAddressInterpreter, ExtensionMappingAddressResolver {

    private static final Logger log = LoggerFactory.getLogger(
            LispExtensionMappingAddressInterpreter.class);

    private static final int IPV4_PREFIX_LENGTH = 32;
    private static final int IPV6_PREFIX_LENGTH = 128;

    @Override
    public boolean supported(ExtensionMappingAddressType type) {

        if (type.equals(LIST_ADDRESS.type())) {
            return true;
        }
        if (type.equals(SEGMENT_ADDRESS.type())) {
            return true;
        }
        if (type.equals(AS_ADDRESS.type())) {
            return true;
        }
        if (type.equals(APPLICATION_DATA_ADDRESS.type())) {
            return true;
        }
        if (type.equals(GEO_COORDINATE_ADDRESS.type())) {
            return true;
        }
        if (type.equals(NAT_ADDRESS.type())) {
            return true;
        }
        if (type.equals(NONCE_ADDRESS.type())) {
            return true;
        }
        if (type.equals(MULTICAST_ADDRESS.type())) {
            return true;
        }
        if (type.equals(TRAFFIC_ENGINEERING_ADDRESS.type())) {
            return true;
        }
        if (type.equals(SOURCE_DEST_ADDRESS.type())) {
            return true;
        }

        return false;
    }

    @Override
    public LispLcafAddress mapMappingAddress(ExtensionMappingAddress mappingAddress) {
        ExtensionMappingAddressType type = mappingAddress.type();

        if (type.equals(LIST_ADDRESS.type())) {

            LispListAddress listAddress = (LispListAddress) mappingAddress;
            LispAfiAddress ipv4 = mapping2afi(listAddress.getIpv4());
            LispAfiAddress ipv6 = mapping2afi(listAddress.getIpv6());

            if (ipv4 != null && ipv6 != null) {
                return new LispListLcafAddress(ImmutableList.of(ipv4, ipv6));
            } else {
                return new LispListLcafAddress(ImmutableList.of());
            }
        }

        if (type.equals(SEGMENT_ADDRESS.type())) {

            LispSegmentAddress segmentAddress = (LispSegmentAddress) mappingAddress;

            return new LispSegmentLcafAddress.SegmentAddressBuilder()
                    .withInstanceId(segmentAddress.getInstanceId())
                    .withAddress(getAfiAddress(segmentAddress.getAddress()))
                    .build();
        }

        if (type.equals(AS_ADDRESS.type())) {

            LispAsAddress asAddress = (LispAsAddress) mappingAddress;

            return new LispAsLcafAddress.AsAddressBuilder()
                            .withAsNumber(asAddress.getAsNumber())
                            .withAddress(getAfiAddress(asAddress.getAddress()))
                            .build();
        }

        if (type.equals(APPLICATION_DATA_ADDRESS.type())) {

            LispAppDataAddress appDataAddress = (LispAppDataAddress) mappingAddress;

            return new LispAppDataLcafAddress.AppDataAddressBuilder()
                            .withProtocol(appDataAddress.getProtocol())
                            .withIpTos(appDataAddress.getIpTos())
                            .withLocalPortLow(appDataAddress.getLocalPortLow())
                            .withLocalPortHigh(appDataAddress.getLocalPortHigh())
                            .withRemotePortLow(appDataAddress.getRemotePortLow())
                            .withRemotePortHigh(appDataAddress.getRemotePortHigh())
                            .withAddress(getAfiAddress(appDataAddress.getAddress()))
                            .build();
        }

        if (type.equals(GEO_COORDINATE_ADDRESS.type())) {

            LispGcAddress gcAddress = (LispGcAddress) mappingAddress;

            return new LispGeoCoordinateLcafAddress.GeoCoordinateAddressBuilder()
                            .withIsNorth(gcAddress.isNorth())
                            .withLatitudeDegree(gcAddress.getLatitudeDegree())
                            .withLatitudeMinute(gcAddress.getLatitudeMinute())
                            .withLatitudeSecond(gcAddress.getLatitudeSecond())
                            .withIsEast(gcAddress.isEast())
                            .withLongitudeDegree(gcAddress.getLongitudeDegree())
                            .withLongitudeMinute(gcAddress.getLongitudeMinute())
                            .withLongitudeSecond(gcAddress.getLongitudeSecond())
                            .withAltitude(gcAddress.getAltitude())
                            .withAddress(getAfiAddress(gcAddress.getAddress()))
                            .build();
        }

        if (type.equals(NAT_ADDRESS.type())) {

            LispNatAddress natAddress = (LispNatAddress) mappingAddress;

            List<LispAfiAddress> aas = Lists.newArrayList();

            natAddress.getRtrRlocAddresses()
                    .forEach(rtr -> aas.add(getAfiAddress(rtr)));

            return new LispNatLcafAddress.NatAddressBuilder()
                            .withMsUdpPortNumber(natAddress.getMsUdpPortNumber())
                            .withEtrUdpPortNumber(natAddress.getEtrUdpPortNumber())
                            .withMsRlocAddress(getAfiAddress(natAddress.getMsRlocAddress()))
                            .withGlobalEtrRlocAddress(
                                    getAfiAddress(natAddress.getGlobalEtrRlocAddress()))
                            .withPrivateEtrRlocAddress(
                                    getAfiAddress(natAddress.getPrivateEtrRlocAddress()))
                            .withRtrRlocAddresses(aas)
                            .build();
        }

        if (type.equals(NONCE_ADDRESS.type())) {

            LispNonceAddress nonceAddress = (LispNonceAddress) mappingAddress;

            return new LispNonceLcafAddress.NonceAddressBuilder()
                            .withNonce(nonceAddress.getNonce())
                            .withAddress(getAfiAddress(nonceAddress.getAddress()))
                            .build();
        }

        if (type.equals(MULTICAST_ADDRESS.type())) {

            LispMulticastAddress multicastAddress = (LispMulticastAddress) mappingAddress;

            return new LispMulticastLcafAddress.MulticastAddressBuilder()
                            .withInstanceId(multicastAddress.getInstanceId())
                            .withSrcAddress(getAfiAddress(multicastAddress.getSrcAddress()))
                            .withSrcMaskLength(multicastAddress.getSrcMaskLength())
                            .withGrpAddress(getAfiAddress(multicastAddress.getGrpAddress()))
                            .withGrpMaskLength(multicastAddress.getGrpMaskLength())
                            .build();
        }

        if (type.equals(TRAFFIC_ENGINEERING_ADDRESS.type())) {

            LispTeAddress teAddress = (LispTeAddress) mappingAddress;

            List<LispTeRecord> records = Lists.newArrayList();

            teAddress.getTeRecords().forEach(record -> {
                LispTeRecord teRecord =
                        new LispTeRecord.TeRecordBuilder()
                                .withIsLookup(record.isLookup())
                                .withIsRlocProbe(record.isRlocProbe())
                                .withIsStrict(record.isStrict())
                                .withRtrRlocAddress(getAfiAddress(
                                        record.getAddress()))
                                .build();
                records.add(teRecord);
            });

            return new LispTeLcafAddress.TeAddressBuilder()
                            .withTeRecords(records)
                            .build();
        }

        if (type.equals(SOURCE_DEST_ADDRESS.type())) {

            LispSrcDstAddress srcDstAddress = (LispSrcDstAddress) mappingAddress;

            return new LispSourceDestLcafAddress.SourceDestAddressBuilder()
                            .withSrcPrefix(getAfiAddress(srcDstAddress.getSrcPrefix()))
                            .withSrcMaskLength(srcDstAddress.getSrcMaskLength())
                            .withDstPrefix(getAfiAddress(srcDstAddress.getDstPrefix()))
                            .withDstMaskLength(srcDstAddress.getDstMaskLength())
                            .build();
        }

        log.error("Unsupported extension mapping address type {}", mappingAddress.type());

        return null;
    }

    @Override
    public ExtensionMappingAddress mapLcafAddress(LispLcafAddress lcafAddress) {

        switch (lcafAddress.getType()) {
            case LIST:
                LispListLcafAddress lcafListAddress = (LispListLcafAddress) lcafAddress;
                MappingAddress ipv4Ma =
                        afi2mapping(lcafListAddress.getAddresses().get(0));
                MappingAddress ipv6Ma =
                        afi2mapping(lcafListAddress.getAddresses().get(1));

                return new LispListAddress.Builder()
                        .withIpv4(ipv4Ma)
                        .withIpv6(ipv6Ma)
                        .build();

            case SEGMENT:
                LispSegmentLcafAddress segmentLcafAddress =
                        (LispSegmentLcafAddress) lcafAddress;

                return new LispSegmentAddress.Builder()
                        .withInstanceId(segmentLcafAddress.getInstanceId())
                        .withAddress(getMappingAddress(segmentLcafAddress.getAddress()))
                        .build();

            case AS:
                LispAsLcafAddress asLcafAddress = (LispAsLcafAddress) lcafAddress;

                return new org.onosproject.drivers.lisp.extensions.LispAsAddress.Builder()
                        .withAsNumber(asLcafAddress.getAsNumber())
                        .withAddress(getMappingAddress(asLcafAddress.getAddress()))
                        .build();

            case APPLICATION_DATA:

                LispAppDataLcafAddress appLcafAddress = (LispAppDataLcafAddress) lcafAddress;

                return new LispAppDataAddress.Builder()
                        .withProtocol(appLcafAddress.getProtocol())
                        .withIpTos(appLcafAddress.getIpTos())
                        .withLocalPortLow(appLcafAddress.getLocalPortLow())
                        .withLocalPortHigh(appLcafAddress.getLocalPortHigh())
                        .withRemotePortLow(appLcafAddress.getRemotePortLow())
                        .withRemotePortHigh(appLcafAddress.getRemotePortHigh())
                        .withAddress(getMappingAddress(appLcafAddress.getAddress()))
                        .build();

            case GEO_COORDINATE:

                LispGeoCoordinateLcafAddress gcLcafAddress =
                        (LispGeoCoordinateLcafAddress) lcafAddress;

                return new LispGcAddress.Builder()
                        .withIsNorth(gcLcafAddress.isNorth())
                        .withLatitudeDegree(gcLcafAddress.getLatitudeDegree())
                        .withLatitudeMinute(gcLcafAddress.getLatitudeMinute())
                        .withLatitudeSecond(gcLcafAddress.getLatitudeSecond())
                        .withIsEast(gcLcafAddress.isEast())
                        .withLongitudeDegree(gcLcafAddress.getLongitudeDegree())
                        .withLongitudeMinute(gcLcafAddress.getLongitudeMinute())
                        .withLongitudeSecond(gcLcafAddress.getLongitudeSecond())
                        .withAltitude(gcLcafAddress.getAltitude())
                        .withAddress(getMappingAddress(gcLcafAddress.getAddress()))
                        .build();

            case NAT:

                LispNatLcafAddress natLcafAddress = (LispNatLcafAddress) lcafAddress;

                List<MappingAddress> mas = Lists.newArrayList();

                natLcafAddress.getRtrRlocAddresses()
                        .forEach(rtr -> mas.add(getMappingAddress(rtr)));

                return new LispNatAddress.Builder()
                        .withMsUdpPortNumber(natLcafAddress.getMsUdpPortNumber())
                        .withEtrUdpPortNumber(natLcafAddress.getEtrUdpPortNumber())
                        .withMsRlocAddress(getMappingAddress(natLcafAddress.getMsRlocAddress()))
                        .withGlobalEtrRlocAddress(
                                getMappingAddress(natLcafAddress.getGlobalEtrRlocAddress()))
                        .withPrivateEtrRlocAddress(
                                getMappingAddress(natLcafAddress.getPrivateEtrRlocAddress()))
                        .withRtrRlocAddresses(mas)
                        .build();

            case NONCE:

                LispNonceLcafAddress nonceLcafAddress = (LispNonceLcafAddress) lcafAddress;

                return new LispNonceAddress.Builder()
                        .withNonce(nonceLcafAddress.getNonce())
                        .withAddress(getMappingAddress(nonceLcafAddress.getAddress()))
                        .build();

            case MULTICAST:

                LispMulticastLcafAddress multiLcafAddress =
                        (LispMulticastLcafAddress) lcafAddress;

                return new LispMulticastAddress.Builder()
                        .withInstanceId(multiLcafAddress.getInstanceId())
                        .withSrcAddress(getMappingAddress(multiLcafAddress.getSrcAddress()))
                        .withSrcMaskLength(multiLcafAddress.getSrcMaskLength())
                        .withGrpAddress(getMappingAddress(multiLcafAddress.getGrpAddress()))
                        .withGrpMaskLength(multiLcafAddress.getGrpMaskLength())
                        .build();

            case TRAFFIC_ENGINEERING:

                LispTeLcafAddress teLcafAddress = (LispTeLcafAddress) lcafAddress;

                List<LispTeAddress.TeRecord> records = Lists.newArrayList();

                teLcafAddress.getTeRecords().forEach(record -> {
                    LispTeAddress.TeRecord teRecord =
                            new LispTeAddress.TeRecord.Builder()
                                    .withIsLookup(record.isLookup())
                                    .withIsRlocProbe(record.isRlocProbe())
                                    .withIsStrict(record.isStrict())
                                    .withRtrRlocAddress(getMappingAddress(
                                            record.getRtrRlocAddress()))
                                    .build();
                    records.add(teRecord);
                });

                return new LispTeAddress.Builder()
                        .withTeRecords(records)
                        .build();

            case SECURITY:

                // TODO: need to implement security type later
                log.warn("security type will be implemented later");

                return null;

            case SOURCE_DEST:

                LispSourceDestLcafAddress srcDstLcafAddress =
                        (LispSourceDestLcafAddress) lcafAddress;


                return new LispSrcDstAddress.Builder()
                        .withSrcPrefix(getMappingAddress(srcDstLcafAddress.getSrcPrefix()))
                        .withSrcMaskLength(srcDstLcafAddress.getSrcMaskLength())
                        .withDstPrefix(getMappingAddress(srcDstLcafAddress.getDstPrefix()))
                        .withDstMaskLength(srcDstLcafAddress.getDstMaskLength())
                        .build();

            case UNSPECIFIED:
            case UNKNOWN:
            default:
                log.error("Unsupported LCAF type {}", lcafAddress.getType());
                return null;
        }
    }

    @Override
    public ExtensionMappingAddress getExtensionMappingAddress(
                                            ExtensionMappingAddressType type) {

        if (type.equals(LIST_ADDRESS.type())) {
            return new LispListAddress();
        }
        if (type.equals(SEGMENT_ADDRESS.type())) {
            return new LispSegmentAddress();
        }
        if (type.equals(AS_ADDRESS.type())) {
            return new LispAsAddress();
        }
        if (type.equals(APPLICATION_DATA_ADDRESS.type())) {
            return new LispAppDataAddress();
        }
        if (type.equals(GEO_COORDINATE_ADDRESS.type())) {
            return new LispGcAddress();
        }
        if (type.equals(NAT_ADDRESS.type())) {
            return new LispNatAddress();
        }
        if (type.equals(NONCE_ADDRESS.type())) {
            return new LispNonceAddress();
        }
        if (type.equals(MULTICAST_ADDRESS.type())) {
            return new LispMulticastAddress();
        }
        if (type.equals(TRAFFIC_ENGINEERING_ADDRESS.type())) {
            return new LispTeAddress();
        }
        if (type.equals(SOURCE_DEST_ADDRESS.type())) {
            return new LispSrcDstAddress();
        }

        return null;
    }

    /**
     * Converts AFI address to generalized mapping address.
     *
     * @param afi IP typed AFI address
     * @return generalized mapping address
     */
    private MappingAddress afi2mapping(LispAfiAddress afi) {
        switch (afi.getAfi()) {
            case IP4:
                IpAddress ipv4Address = ((LispIpv4Address) afi).getAddress();
                IpPrefix ipv4Prefix = IpPrefix.valueOf(ipv4Address, IPV4_PREFIX_LENGTH);
                return MappingAddresses.ipv4MappingAddress(ipv4Prefix);
            case IP6:
                IpAddress ipv6Address = ((LispIpv6Address) afi).getAddress();
                IpPrefix ipv6Prefix = IpPrefix.valueOf(ipv6Address, IPV6_PREFIX_LENGTH);
                return MappingAddresses.ipv6MappingAddress(ipv6Prefix);
            default:
                log.warn("Only support to convert IP address type");
                break;
        }
        return null;
    }

    /**
     * Converts mapping address to AFI address.
     *
     * @param address generalized mapping address
     * @return IP typed AFI address
     */
    private LispAfiAddress mapping2afi(MappingAddress address) {
        switch (address.type()) {
            case IPV4:
                IpPrefix ipv4Prefix = ((IPMappingAddress) address).ip();
                return new LispIpv4Address(ipv4Prefix.address());
            case IPV6:
                IpPrefix ipv6Prefix = ((IPMappingAddress) address).ip();
                return new LispIpv6Address(ipv6Prefix.address());
            default:
                log.warn("Only support to convert IP address type");
                break;
        }
        return null;
    }

    /**
     * Converts LispAfiAddress into abstracted mapping address.
     *
     * @param address LispAfiAddress
     * @return abstracted mapping address
     */
    private MappingAddress getMappingAddress(LispAfiAddress address) {

        if (address == null) {
            log.warn("Address is not specified.");
            return null;
        }

        switch (address.getAfi()) {
            case IP4:
                return afi2mapping(address);
            case IP6:
                return afi2mapping(address);
            case AS:
                int asNum = ((org.onosproject.lisp.msg.types.LispAsAddress) address).getASNum();
                return MappingAddresses.asMappingAddress(String.valueOf(asNum));
            case DISTINGUISHED_NAME:
                String dn = ((LispDistinguishedNameAddress)
                        address).getDistinguishedName();
                return MappingAddresses.dnMappingAddress(dn);
            case MAC:
                MacAddress macAddress = ((LispMacAddress) address).getAddress();
                return MappingAddresses.ethMappingAddress(macAddress);
            case LCAF:
                LispLcafAddress lcafAddress = (LispLcafAddress) address;
                return MappingAddresses.extensionMappingAddressWrapper(mapLcafAddress(lcafAddress));
            default:
                log.warn("Unsupported address AFI type {}", address.getAfi());
                break;
        }

        return null;
    }

    /**
     * Converts mapping address into afi address.
     *
     * @param address mapping address
     * @return afi address
     */
    private LispAfiAddress getAfiAddress(MappingAddress address) {

        if (address == null) {
            log.warn("Address is not specified.");
            return null;
        }

        switch (address.type()) {
            case IPV4:
                return mapping2afi(address);
            case IPV6:
                return mapping2afi(address);
            case AS:
                int asNum = ((org.onosproject.lisp.msg.types.LispAsAddress) address).getASNum();
                return new org.onosproject.lisp.msg.types.LispAsAddress(asNum);
            case DN:
                String dn = ((LispDistinguishedNameAddress) address).getDistinguishedName();
                return new LispDistinguishedNameAddress(dn);
            case ETH:
                MacAddress macAddress = ((LispMacAddress) address).getAddress();
                return new LispMacAddress(macAddress);
            case EXTENSION:
                ExtensionMappingAddress extAddress = (ExtensionMappingAddress) address;
                return mapMappingAddress(extAddress);
            default:
                log.warn("Unsupported address type {}", address.type());
                break;
        }

        return null;
    }
}
