/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.opencord.cordvtn.impl;

import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.opencord.cordvtn.api.Constants;
import org.opencord.cordvtn.api.CordVtnConfig;
import org.opencord.cordvtn.api.core.Instance;
import org.opencord.cordvtn.api.core.ServiceNetworkEvent;
import org.opencord.cordvtn.api.core.ServiceNetworkListener;
import org.opencord.cordvtn.api.core.ServiceNetworkService;
import org.opencord.cordvtn.api.net.ServiceNetwork;
import org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType;
import org.opencord.cordvtn.api.node.CordVtnNode;
import org.opencord.cordvtn.api.node.CordVtnNodeService;
import org.opencord.cordvtn.api.node.CordVtnNodeState;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;

import java.nio.ByteBuffer;
import java.util.Dictionary;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.opencord.cordvtn.api.Constants.DEFAULT_GATEWAY_MAC_STR;
import static org.opencord.cordvtn.api.net.ServiceNetwork.NetworkType.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Handles ARP requests for virtual network service IPs.
 */
@Component(immediate = true)
public class CordVtnArpProxy {
    protected final Logger log = getLogger(getClass());

    private static final String PRIVATE_GATEWAY_MAC = "privateGatewayMac";

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PacketService packetService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected HostService hostService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService netConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ComponentConfigService compConfigService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CordVtnNodeService nodeService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ServiceNetworkService snetService;

    @Property(name = PRIVATE_GATEWAY_MAC, value = DEFAULT_GATEWAY_MAC_STR,
            label = "Fake MAC address for virtual network gateway")
    private String privateGatewayMacStr = DEFAULT_GATEWAY_MAC_STR;
    private MacAddress privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);

    private final PacketProcessor packetProcessor = new InternalPacketProcessor();
    private final Map<IpAddress, MacAddress> gateways = Maps.newConcurrentMap();

    private NetworkConfigListener configListener = new InternalConfigListener();
    private ServiceNetworkListener snetListener = new InternalServiceNetworkListener();
    private ApplicationId appId;

    @Activate
    protected void activate() {
        appId = coreService.registerApplication(Constants.CORDVTN_APP_ID);
        compConfigService.registerProperties(getClass());

        netConfigService.addListener(configListener);
        readPublicGateways();
        snetService.addListener(snetListener);
        readPrivateGateways();

        packetService.addProcessor(packetProcessor, PacketProcessor.director(0));
        requestPacket();

        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        packetService.removeProcessor(packetProcessor);
        snetService.removeListener(snetListener);
        netConfigService.removeListener(configListener);
        compConfigService.unregisterProperties(getClass(), false);

        log.info("Stopped");
    }

    @Modified
    protected void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();
        String updatedMac;

        updatedMac = Tools.get(properties, PRIVATE_GATEWAY_MAC);
        if (!Strings.isNullOrEmpty(updatedMac) &&
                !updatedMac.equals(privateGatewayMacStr)) {
            privateGatewayMacStr = updatedMac;
            privateGatewayMac = MacAddress.valueOf(privateGatewayMacStr);
        }

        log.info("Modified");
    }

    /**
     * Requests ARP packet.
     */
    private void requestPacket() {
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.ARP.ethType().toShort())
                .build();

        packetService.requestPackets(
                selector,
                PacketPriority.CONTROL,
                appId,
                Optional.empty());
    }

    /**
     * Cancels ARP packet.
     */
    private void cancelPacket() {
        TrafficSelector selector = DefaultTrafficSelector.builder()
                .matchEthType(EthType.EtherType.ARP.ethType().toShort())
                .build();

        packetService.cancelPackets(
                selector,
                PacketPriority.CONTROL,
                appId,
                Optional.empty());
    }

    private void readPrivateGateways() {
        snetService.serviceNetworks().stream()
                .filter(net -> net.type() == PRIVATE || net.type() == VSG)
                .filter(net -> net.serviceIp() != null)
                .forEach(net -> addGateway(net.serviceIp(), privateGatewayMac));
    }

    /**
     * Adds a given gateway IP and MAC address to this ARP proxy.
     *
     * @param gatewayIp gateway ip address
     * @param gatewayMac gateway mac address
     */
    private void addGateway(IpAddress gatewayIp, MacAddress gatewayMac) {
        checkNotNull(gatewayIp, "Gateway IP address cannot be null");
        checkArgument(gatewayMac != null && gatewayMac != MacAddress.NONE,
                      "Gateway MAC address cannot be null or NONE");

        MacAddress existing = gateways.get(gatewayIp);
        if (existing != null && !existing.equals(privateGatewayMac) &&
                gatewayMac.equals(privateGatewayMac)) {
            // this is public gateway IP and MAC configured via netcfg
            // don't update with private gateway MAC
            return;
        }
        gateways.put(gatewayIp, gatewayMac);
        log.debug("Added ARP proxy entry IP:{} MAC:{}", gatewayIp, gatewayMac);
    }

    /**
     * Removes a given service IP address from this ARP proxy.
     *
     * @param gatewayIp gateway ip address
     */
    private void removeGateway(IpAddress gatewayIp) {
        checkNotNull(gatewayIp);
        MacAddress existing = gateways.get(gatewayIp);
        if (existing == null) {
            return;
        }
        if (!existing.equals(privateGatewayMac)) {
            // this is public gateway IP and MAC configured via netcfg
            // do nothing
            return;
        }
        gateways.remove(gatewayIp);
        log.debug("Removed ARP proxy entry for IP:{} MAC: {}", gatewayIp, existing);
    }

    /**
     * Emits ARP reply with fake MAC address for a given ARP request.
     * It only handles requests for the registered gateway IPs and host IPs.
     *
     * @param context packet context
     * @param ethPacket ethernet packet
     */
    private void processArpRequest(PacketContext context, Ethernet ethPacket) {
        ARP arpPacket = (ARP) ethPacket.getPayload();
        Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());

        MacAddress gatewayMac = gateways.get(targetIp);
        MacAddress replyMac = gatewayMac != null ? gatewayMac :
                getMacFromHostService(targetIp);

        if (replyMac.equals(MacAddress.NONE)) {
            forwardArpRequest(context, ethPacket);
            return;
        }

        Ethernet ethReply = ARP.buildArpReply(
                targetIp,
                replyMac,
                ethPacket);

        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(context.inPacket().receivedFrom().port())
                .build();

        packetService.emit(new DefaultOutboundPacket(
                context.inPacket().receivedFrom().deviceId(),
                treatment,
                ByteBuffer.wrap(ethReply.serialize())));

        context.block();
    }

    private void processArpReply(PacketContext context, Ethernet ethPacket) {
        ARP arpPacket = (ARP) ethPacket.getPayload();
        Ip4Address targetIp = Ip4Address.valueOf(arpPacket.getTargetProtocolAddress());

        DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
        Host host = hostService.getHostsByIp(targetIp).stream()
                .filter(h -> h.location().deviceId().equals(deviceId))
                .findFirst()
                .orElse(null);

        if (host == null) {
            // do nothing for the unknown ARP reply
            log.trace("No host found for {} in {}", targetIp, deviceId);
            context.block();
            return;
        }

        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                .setOutput(host.location().port())
                .build();

        packetService.emit(new DefaultOutboundPacket(
                deviceId,
                treatment,
                ByteBuffer.wrap(ethPacket.serialize())));

        context.block();
    }

    private void forwardArpRequest(PacketContext context, Ethernet ethPacket) {
        DeviceId deviceId = context.inPacket().receivedFrom().deviceId();
        PortNumber inputPort = context.inPacket().receivedFrom().port();

        Host host = hostService.getHost(HostId.hostId(ethPacket.getSourceMAC()));
        if (host == null) {
            context.block();
            return;
        }

        NetworkType networkType = Instance.of(host).netType();
        if (networkType != MANAGEMENT_HOST && networkType != FLAT) {
            context.block();
            log.trace("Failed to handle ARP request");
            return;
        }

        PortNumber outputPort = networkType == MANAGEMENT_HOST ?
                hostMgmtPort(deviceId) : dataPort(deviceId);
        if (inputPort.equals(outputPort)) {
            context.block();
            return;
        }

        if (outputPort != null) {
            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                    .setOutput(outputPort)
                    .build();

            packetService.emit(new DefaultOutboundPacket(
                    context.inPacket().receivedFrom().deviceId(),
                    treatment,
                    ByteBuffer.wrap(ethPacket.serialize())));
        } else {
            log.trace("Failed to handle ARP request");
        }

        context.block();
    }

    private PortNumber hostMgmtPort(DeviceId deviceId) {
        CordVtnNode node = nodeService.node(deviceId);
        if (node == null || node.state() != CordVtnNodeState.COMPLETE ||
                node.hostManagementInterface() == null) {
            return null;
        }
        Optional<Port> port = deviceService.getPorts(deviceId).stream()
                .filter(p -> p.annotations().value(PORT_NAME)
                        .equals(node.hostManagementInterface()) &&
                        p.isEnabled())
                .findAny();
        return port.map(Port::number).orElse(null);
    }

    private PortNumber dataPort(DeviceId deviceId) {
        CordVtnNode node = nodeService.node(deviceId);
        if (node == null || node.state() != CordVtnNodeState.COMPLETE ||
                node.dataInterface() == null) {
            return null;
        }
        Optional<Port> port = deviceService.getPorts(deviceId).stream()
                .filter(p -> p.annotations().value(PORT_NAME)
                        .equals(node.dataInterface()) &&
                        p.isEnabled())
                .findAny();
        return port.map(Port::number).orElse(null);
    }

    /**
     * Emits gratuitous ARP when a gateway mac address has been changed.
     *
     * @param gatewayIp gateway ip address to update MAC
     * @param instances set of instances to send gratuitous ARP packet
     */
    private void sendGratuitousArp(IpAddress gatewayIp, Set<Instance> instances) {
        MacAddress gatewayMac = gateways.get(gatewayIp);
        if (gatewayMac == null) {
            log.debug("Gateway {} is not registered to ARP proxy", gatewayIp);
            return;
        }

        Ethernet ethArp = buildGratuitousArp(gatewayIp.getIp4Address(), gatewayMac);
        instances.forEach(instance -> {
            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
                    .setOutput(instance.portNumber())
                    .build();

            packetService.emit(new DefaultOutboundPacket(
                    instance.deviceId(),
                    treatment,
                    ByteBuffer.wrap(ethArp.serialize())));
        });
    }

    /**
     * Builds gratuitous ARP packet with a given IP and MAC address.
     *
     * @param ip ip address for TPA and SPA
     * @param mac new mac address
     * @return ethernet packet
     */
    private Ethernet buildGratuitousArp(IpAddress ip, MacAddress mac) {
        Ethernet eth = new Ethernet();

        eth.setEtherType(Ethernet.TYPE_ARP);
        eth.setSourceMACAddress(mac);
        eth.setDestinationMACAddress(MacAddress.BROADCAST);

        ARP arp = new ARP();
        arp.setOpCode(ARP.OP_REQUEST);
        arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
        arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
        arp.setProtocolType(ARP.PROTO_TYPE_IP);
        arp.setProtocolAddressLength((byte) Ip4Address.BYTE_LENGTH);

        arp.setSenderHardwareAddress(mac.toBytes());
        arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
        arp.setSenderProtocolAddress(ip.getIp4Address().toOctets());
        arp.setTargetProtocolAddress(ip.getIp4Address().toOctets());

        eth.setPayload(arp);
        return eth;
    }

    /**
     * Returns MAC address of a host with a given target IP address by asking to
     * host service. It does not support overlapping IP.
     *
     * @param targetIp target ip
     * @return mac address, or NONE mac address if it fails to find the mac
     */
    private MacAddress getMacFromHostService(IpAddress targetIp) {
        checkNotNull(targetIp);

        Host host = hostService.getHostsByIp(targetIp)
                .stream()
                .findFirst()
                .orElse(null);

        if (host != null) {
            log.trace("Found MAC from host service for {}", targetIp);
            return host.mac();
        } else {
            return MacAddress.NONE;
        }
    }

    private class InternalPacketProcessor implements PacketProcessor {

        @Override
        public void process(PacketContext context) {
            if (context.isHandled()) {
                return;
            }
            Ethernet ethPacket = context.inPacket().parsed();
            if (ethPacket == null || ethPacket.getEtherType() != Ethernet.TYPE_ARP) {
                return;
            }

            ARP arpPacket = (ARP) ethPacket.getPayload();
            switch (arpPacket.getOpCode()) {
                case ARP.OP_REQUEST:
                    processArpRequest(context, ethPacket);
                    break;
                case ARP.OP_REPLY:
                    processArpReply(context, ethPacket);
                    break;
                default:
                    break;
            }
        }
    }

    private class InternalServiceNetworkListener implements ServiceNetworkListener {

        @Override
        public boolean isRelevant(ServiceNetworkEvent event) {
            ServiceNetwork snet = event.subject();
            return snet.serviceIp() != null;
        }

        @Override
        public void event(ServiceNetworkEvent event) {
            ServiceNetwork snet = event.subject();
            switch (event.type()) {
                case SERVICE_NETWORK_CREATED:
                    if (snet.type() == PRIVATE || snet.type() == VSG) {
                        addGateway(snet.serviceIp(), privateGatewayMac);
                    }
                    break;
                case SERVICE_NETWORK_UPDATED:
                    if (snet.type() == PRIVATE || snet.type() == VSG) {
                        addGateway(snet.serviceIp(), privateGatewayMac);
                    } else {
                        // don't service ARP for the other network gateway
                        removeGateway(snet.serviceIp());
                    }
                    break;
                case SERVICE_NETWORK_REMOVED:
                    removeGateway(snet.serviceIp());
                    break;
                case SERVICE_PORT_CREATED:
                case SERVICE_PORT_UPDATED:
                case SERVICE_PORT_REMOVED:
                default:
                    // do nothing for the other events
                    break;
            }
        }
    }

    private void readPublicGateways() {
        CordVtnConfig config = netConfigService.getConfig(appId, CordVtnConfig.class);
        if (config == null) {
            log.warn("No configuration found");
            return;
        }

        config.publicGateways().forEach(this::addGateway);
        // TODO send gratuitous arp in case the MAC is changed
    }

    private class InternalConfigListener implements NetworkConfigListener {

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            return event.configClass().equals(CordVtnConfig.class);
        }

        @Override
        public void event(NetworkConfigEvent event) {

            switch (event.type()) {
                case CONFIG_ADDED:
                case CONFIG_UPDATED:
                    readPublicGateways();
                    break;
                default:
                    break;
            }
        }
    }
}
