/*
 * Copyright 2015-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.onosproject.virtualbng;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
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.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.PointToPointIntent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * This is a virtual Broadband Network Gateway (BNG) application. It mainly
 * has 3 functions:
 * (1) assigns and replies a public IP address to a REST request with a private
 * IP address
 * (2) maintains the mapping from the private IP address to the public IP address
 * (3) installs point to point intents for the host configured with private IP
 * address to access Internet
 */
@Component(immediate = true)
@Service
public class VbngManager implements VbngService {

    private static final String APP_NAME = "org.onosproject.virtualbng";
    private static final String VBNG_MAP_NAME = "vbng_mapping";

    private final Logger log = LoggerFactory.getLogger(getClass());

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentService intentService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected VbngConfigurationService vbngConfigurationService;

    private ApplicationId appId;
    private Map<IpAddress, PointToPointIntent> p2pIntentsFromHost;
    private Map<IpAddress, PointToPointIntent> p2pIntentsToHost;

    // This map stores the mapping from the private IP addresses to VcpeHost.
    // The IP addresses in this map are all the private IP addresses we failed
    // to create vBNGs due to the next hop host was not in ONOS.
    private Map<IpAddress, VcpeHost> privateIpAddressMap;

    // Store the mapping from hostname to connect point
    private Map<String, ConnectPoint> nodeToPort;

    private HostListener hostListener;
    private IpAddress nextHopIpAddress;

    private static final DeviceId FABRIC_DEVICE_ID =
            DeviceId.deviceId("of:8f0e486e73000187");

    @Activate
    public void activate() {
        appId = coreService.registerApplication(APP_NAME);
        p2pIntentsFromHost = new ConcurrentHashMap<>();
        p2pIntentsToHost = new ConcurrentHashMap<>();
        privateIpAddressMap = new ConcurrentHashMap<>();

        nextHopIpAddress = vbngConfigurationService.getNextHopIpAddress();
        nodeToPort = vbngConfigurationService.getNodeToPort();
        hostListener = new InternalHostListener();
        hostService.addListener(hostListener);

        log.info("vBNG Started");

        // Recover the status before vBNG restarts
        statusRecovery();
    }

    @Deactivate
    public void deactivate() {
        hostService.removeListener(hostListener);
        log.info("vBNG Stopped");
    }

    /**
     * Recovers from XOS record. Re-sets up the mapping between private IP
     * address and public IP address, re-calculates intents and re-installs
     * those intents.
     */
    private void statusRecovery() {
        log.info("vBNG starts to recover from XOS record......");
        ObjectNode map;
        try {
            RestClient restClient =
                    new RestClient(vbngConfigurationService.getXosIpAddress(),
                            vbngConfigurationService.getXosRestPort());
            map = restClient.getRest();
        } catch (Exception e) {
            log.error("Could not contact XOS", e);
            return;
        }
        if (map == null) {
            log.info("Stop to recover vBNG status due to the vBNG map "
                    + "is null!");
            return;
        }

        log.info("Get record from XOS: {}", map);

        ArrayNode array = (ArrayNode) map.get(VBNG_MAP_NAME);
        Iterator<JsonNode> entries = array.elements();
        while (entries.hasNext()) {
            ObjectNode entry = (ObjectNode) entries.next();

            IpAddress hostIpAdddress =
                    IpAddress.valueOf(entry.get("private_ip").asText());
            IpAddress publicIpAddress =
                    IpAddress.valueOf(entry.get("routeable_subnet").asText());
            MacAddress macAddress =
                    MacAddress.valueOf(entry.get("mac").asText());
            String hostName = entry.get("hostname").asText();

            // Create vBNG
            createVbng(hostIpAdddress, publicIpAddress, macAddress, hostName);

        }
    }

    /**
     * Creates a new vBNG.
     *
     * @param privateIpAddress a private IP address
     * @param publicIpAddress the public IP address for the private IP address
     * @param hostMacAddress the MAC address for the private IP address
     * @param hostName the host name for the private IP address
     */
    private void createVbng(IpAddress privateIpAddress,
                            IpAddress publicIpAddress,
                            MacAddress hostMacAddress,
                            String hostName) {
        boolean result = vbngConfigurationService
                .assignSpecifiedPublicIp(publicIpAddress, privateIpAddress);
        if (!result) {
            log.info("Assign public IP address {} for private IP address {} "
                    + "failed!", publicIpAddress, privateIpAddress);
            log.info("Failed to create vBNG for private IP address {}",
                     privateIpAddress);
            return;
        }
        log.info("[ADD] Private IP to Public IP mapping: {} --> {}",
                 privateIpAddress, publicIpAddress);

        // Setup paths between the host configured with private IP and
        // next hop
        if (!setupForwardingPaths(privateIpAddress, publicIpAddress,
                                  hostMacAddress, hostName)) {
            privateIpAddressMap.put(privateIpAddress,
                                    new VcpeHost(hostMacAddress, hostName));
        }
    }

    @Override
    public IpAddress createVbng(IpAddress privateIpAddress,
                                MacAddress hostMacAddress,
                                String hostName) {

        IpAddress publicIpAddress =
                vbngConfigurationService.getAvailablePublicIpAddress(
                                                     privateIpAddress);
        if (publicIpAddress == null) {
            log.info("Did not find an available public IP address to use.");
            return null;
        }
        log.info("[ADD] Private IP to Public IP mapping: {} --> {}",
                 privateIpAddress, publicIpAddress);

        // Setup paths between the host configured with private IP and
        // next hop
        if (!setupForwardingPaths(privateIpAddress, publicIpAddress,
                                  hostMacAddress, hostName)) {
            privateIpAddressMap.put(privateIpAddress,
                                    new VcpeHost(hostMacAddress, hostName));
        }
        return publicIpAddress;
    }

    @Override
    public IpAddress deleteVbng(IpAddress privateIpAddress) {
        // Recycle the public IP address assigned to this private IP address.
        // Recycling will also delete the mapping entry from the private IP
        // address to public IP address.
        IpAddress assignedPublicIpAddress = vbngConfigurationService
                .recycleAssignedPublicIpAddress(privateIpAddress);
        if (assignedPublicIpAddress == null) {
            return null;
        }

        // Remove the private IP address from privateIpAddressMap
        privateIpAddressMap.remove(privateIpAddress);

        // Remove intents
        removeForwardingPaths(privateIpAddress);

        return assignedPublicIpAddress;
    }

    /**
     * Removes the forwarding paths in both two directions between host
     * configured with private IP and next hop.
     *
     * @param privateIp the private IP address of a local host
     */
    private void removeForwardingPaths(IpAddress privateIp) {
        PointToPointIntent toNextHopIntent =
                p2pIntentsFromHost.remove(privateIp);
        if (toNextHopIntent != null) {
            intentService.withdraw(toNextHopIntent);
            //intentService.purge(toNextHopIntent);
        }
        PointToPointIntent toLocalHostIntent =
                p2pIntentsToHost.remove(privateIp);
        if (toLocalHostIntent != null) {
            intentService.withdraw(toLocalHostIntent);
            //intentService.purge(toLocalHostIntent);
        }
    }

    /**
     * Sets up forwarding paths in both two directions between host configured
     * with private IP and next hop.
     *
     * @param privateIp the private IP address of a local host
     * @param publicIp the public IP address assigned for the private IP address
     * @param hostMacAddress the MAC address for the IP address
     * @param hostName the host name for the IP address
     */
    private boolean setupForwardingPaths(IpAddress privateIp,
                                         IpAddress publicIp,
                                         MacAddress hostMacAddress,
                                         String hostName) {
        checkNotNull(privateIp);
        checkNotNull(publicIp);
        checkNotNull(hostMacAddress);
        checkNotNull(hostName);

        if (nextHopIpAddress == null) {
            log.warn("Did not find next hop IP address");
            return false;
        }

        // If there are already intents for private IP address in the system,
        // we will do nothing and directly return.
        if (p2pIntentsFromHost.containsKey(privateIp)
                && p2pIntentsToHost.containsKey(privateIp)) {
            return true;
        }

        Host nextHopHost = null;
        if (!hostService.getHostsByIp(nextHopIpAddress).isEmpty()) {
            nextHopHost = hostService.getHostsByIp(nextHopIpAddress)
                    .iterator().next();
        } else {
            hostService.startMonitoringIp(nextHopIpAddress);
            if (hostService.getHostsByIp(privateIp).isEmpty()) {
                hostService.startMonitoringIp(privateIp);
            }
            return false;
        }

        ConnectPoint nextHopConnectPoint =
                new ConnectPoint(nextHopHost.location().elementId(),
                                 nextHopHost.location().port());
        ConnectPoint localHostConnectPoint = nodeToPort.get(hostName);

        // Generate and install intent for traffic from host configured with
        // private IP
        if (!p2pIntentsFromHost.containsKey(privateIp)) {
            PointToPointIntent toNextHopIntent
                    = srcMatchIntentGenerator(privateIp,
                                              publicIp,
                                              nextHopHost.mac(),
                                              nextHopConnectPoint,
                                              localHostConnectPoint
                                              );
            p2pIntentsFromHost.put(privateIp, toNextHopIntent);
            intentService.submit(toNextHopIntent);
        }

        // Generate and install intent for traffic to host configured with
        // private IP
        if (!p2pIntentsToHost.containsKey(privateIp)) {
            PointToPointIntent toLocalHostIntent
                    = dstMatchIntentGenerator(publicIp,
                                              privateIp,
                                              hostMacAddress,
                                              localHostConnectPoint,
                                              nextHopConnectPoint);
            p2pIntentsToHost.put(privateIp, toLocalHostIntent);
            intentService.submit(toLocalHostIntent);
        }

        return true;
    }

    /**
     * Listener for host events.
     */
    private class InternalHostListener implements HostListener {
        @Override
        public void event(HostEvent event) {
            log.debug("Received HostEvent {}", event);

            Host host = event.subject();
            if (event.type() != HostEvent.Type.HOST_ADDED) {
                return;
            }

            for (IpAddress ipAddress: host.ipAddresses()) {
                // The POST method from XOS gives us MAC and host name, so we
                // do not need to do anything after receive a vCPE host event
                // for now.
                /*if (privateIpAddressSet.contains(ipAddress)) {
                    createVbngAgain(ipAddress);
                }*/

                if (nextHopIpAddress != null &&
                        ipAddress.equals(nextHopIpAddress)) {

                    for (Entry<IpAddress, VcpeHost> entry:
                        privateIpAddressMap.entrySet()) {
                        createVbngAgain(entry.getKey());
                    }

                }
            }
        }
    }

    /**
     * Tries to create vBNG again after receiving a host event if the IP
     * address of the host is the next hop IP address.
     *
     * @param privateIpAddress the private IP address
     */
    private void createVbngAgain(IpAddress privateIpAddress) {
        IpAddress publicIpAddress = vbngConfigurationService
                .getAssignedPublicIpAddress(privateIpAddress);
        if (publicIpAddress == null) {
            // We only need to handle the private IP addresses for which we
            // already returned the REST replies with assigned public IP
            // addresses. If a private IP addresses does not have an assigned
            // public IP address, we should not get it an available public IP
            // address here, and we should delete it in the unhandled private
            // IP address map.
            privateIpAddressMap.remove(privateIpAddress);
            return;
        }
        VcpeHost vcpeHost = privateIpAddressMap.get(privateIpAddress);
        if (setupForwardingPaths(privateIpAddress, publicIpAddress,
                                 vcpeHost.macAddress, vcpeHost.hostName)) {
            privateIpAddressMap.remove(privateIpAddress);
        }
    }

    /**
     * PointToPointIntent Generator.
     * <p>
     * The intent will match the source IP address in packet, rewrite the
     * source IP address, and rewrite the destination MAC address.
     * </p>
     *
     * @param srcIpAddress the source IP address in packet to match
     * @param newSrcIpAddress the new source IP address to set
     * @param dstMacAddress the destination MAC address to set
     * @param dstConnectPoint the egress point
     * @param srcConnectPoint the ingress point
     * @return a PointToPointIntent
     */
    private PointToPointIntent srcMatchIntentGenerator(
                                             IpAddress srcIpAddress,
                                             IpAddress newSrcIpAddress,
                                             MacAddress dstMacAddress,
                                             ConnectPoint dstConnectPoint,
                                             ConnectPoint srcConnectPoint) {
        checkNotNull(srcIpAddress);
        checkNotNull(newSrcIpAddress);
        checkNotNull(dstMacAddress);
        checkNotNull(dstConnectPoint);
        checkNotNull(srcConnectPoint);

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_IPV4);
        selector.matchIPSrc(IpPrefix.valueOf(srcIpAddress,
                                             IpPrefix.MAX_INET_MASK_LENGTH));

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.setEthDst(dstMacAddress);
        treatment.setIpSrc(newSrcIpAddress);

        Key key = Key.of(srcIpAddress.toString() + "MatchSrc", appId);
        PointToPointIntent intent = PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector.build())
                .treatment(treatment.build())
                .egressPoint(dstConnectPoint)
                .ingressPoint(srcConnectPoint)
                .build();

        log.info("Generated a PointToPointIntent for traffic from local host "
                + ": {}", intent);
        return intent;
    }

    /**
     * PointToPointIntent Generator.
     * <p>
     * The intent will match the destination IP address in packet, rewrite the
     * destination IP address, and rewrite the destination MAC address.
     * </p>
     *
     * @param dstIpAddress the destination IP address in packet to match
     * @param newDstIpAddress the new destination IP address to set
     * @param dstMacAddress the destination MAC address to set
     * @param dstConnectPoint the egress point
     * @param srcConnectPoint the ingress point
     * @return a PointToPointIntent
     */
    private PointToPointIntent dstMatchIntentGenerator(
                                                IpAddress dstIpAddress,
                                                IpAddress newDstIpAddress,
                                                MacAddress dstMacAddress,
                                                ConnectPoint dstConnectPoint,
                                                ConnectPoint srcConnectPoint) {
        checkNotNull(dstIpAddress);
        checkNotNull(newDstIpAddress);
        checkNotNull(dstMacAddress);
        checkNotNull(dstConnectPoint);
        checkNotNull(srcConnectPoint);

        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        selector.matchEthType(Ethernet.TYPE_IPV4);
        selector.matchIPDst(IpPrefix.valueOf(dstIpAddress,
                                             IpPrefix.MAX_INET_MASK_LENGTH));

        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        treatment.setEthDst(dstMacAddress);
        treatment.setIpDst(newDstIpAddress);

        Key key = Key.of(newDstIpAddress.toString() + "MatchDst", appId);
        PointToPointIntent intent = PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector.build())
                .treatment(treatment.build())
                .egressPoint(dstConnectPoint)
                .ingressPoint(srcConnectPoint)
                .build();
        log.info("Generated a PointToPointIntent for traffic to local host "
                + ": {}", intent);

        return intent;
    }

    /**
     * Constructor to store the a vCPE host info.
     */
    private class VcpeHost {
        MacAddress macAddress;
        String hostName;
        public VcpeHost(MacAddress macAddress, String hostName) {
            this.macAddress = macAddress;
            this.hostName = hostName;
        }
    }
}
