/*
 * 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.FilteredConnectPoint;
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())
                .filteredEgressPoint(new FilteredConnectPoint(dstConnectPoint))
                .filteredIngressPoint(new FilteredConnectPoint(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())
                .filteredEgressPoint(new FilteredConnectPoint(dstConnectPoint))
                .filteredIngressPoint(new FilteredConnectPoint(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;
        }
    }
}
