/*
 * 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.onosproject.castor;
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.IPv4;
import org.onlab.packet.IPv6;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.FilteredConnectPoint;
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.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.intentsync.IntentSynchronizationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

/**
 * Manages the connectivity requirements between peers.
 */
@Component(immediate = true, enabled = true)
@Service
public class ConnectivityManager implements ConnectivityManagerService {

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected IntentSynchronizationService intentSynchronizer;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CastorStore castorStore;

    private static final int PRIORITY_OFFSET = 1000;
    private static final int FLOW_PRIORITY = 500;
    private static final String SUFFIX_DST = "dst";
    private static final String SUFFIX_SRC = "src";
    private static final String SUFFIX_ICMP = "icmp";

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

    private static final short BGP_PORT = 179;

    private ApplicationId appId;

    @Activate
    public void activate() {
        appId = coreService.getAppId(Castor.CASTOR_APP);
    }

    @Deactivate
    public void deactivate() {
    }

    /**
     * Inputs the Route Servers.
     */
    @Override
    public void start(Peer server) {
        //routeServers.add(server);
        //allPeers.add(server);
        castorStore.storePeer(server);
        castorStore.storeServer(server);
    }

    /**
     * Stops the peer connectivity manager.
     */
    public void stop() {};

    /**
     * Sets up paths to establish connectivity between all internal.
     * BGP speakers and external BGP peers.
     */
    @Override
    public void setUpConnectivity(Peer peer) {

        if (!castorStore.getCustomers().contains(peer)) {
            castorStore.storePeer(peer);
            castorStore.storeCustomer(peer);
        }

        for (Peer routeServer : castorStore.getServers()) {
            log.debug("Start to set up BGP paths for BGP peer and Route Server"
                    + peer + "&" + routeServer);

            buildSpeakerIntents(routeServer, peer).forEach(i -> {
                    castorStore.storePeerIntent(i.key(), i);
                    intentSynchronizer.submit(i);
                });
        }
    }

    private Collection<PointToPointIntent> buildSpeakerIntents(Peer speaker, Peer peer) {
        List<PointToPointIntent> intents = new ArrayList<>();

        IpAddress peerAddress = IpAddress.valueOf(peer.getIpAddress());
        IpAddress speakerAddress = IpAddress.valueOf(speaker.getIpAddress());

        checkNotNull(peerAddress);

        intents.addAll(buildIntents(ConnectPoint.deviceConnectPoint(speaker.getPort()), speakerAddress,
                ConnectPoint.deviceConnectPoint(peer.getPort()), peerAddress));

        return intents;
    }

    /**
     * Builds the required intents between the two pairs of connect points and
     * IP addresses.
     *
     * @param portOne the first connect point
     * @param ipOne the first IP address
     * @param portTwo the second connect point
     * @param ipTwo the second IP address
     * @return the intents to install
     */
    private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
                                                        IpAddress ipOne,
                                                        ConnectPoint portTwo,
                                                        IpAddress ipTwo) {

        List<PointToPointIntent> intents = new ArrayList<>();

        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
        TrafficSelector selector;
        Key key;

        byte tcpProtocol;
        byte icmpProtocol;

        if (ipOne.isIp4()) {
            tcpProtocol = IPv4.PROTOCOL_TCP;
            icmpProtocol = IPv4.PROTOCOL_ICMP;
        } else {
            tcpProtocol = IPv6.PROTOCOL_TCP;
            icmpProtocol = IPv6.PROTOCOL_ICMP6;
        }

        // Path from BGP speaker to BGP peer matching source TCP port 179
        selector = buildSelector(tcpProtocol,
                ipOne,
                ipTwo,
                BGP_PORT,
                null);

        key = buildKey(ipOne, ipTwo, SUFFIX_SRC);

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .filteredIngressPoint(new FilteredConnectPoint(portOne))
                .filteredEgressPoint(new FilteredConnectPoint(portTwo))
                .priority(PRIORITY_OFFSET)
                .build());

        // Path from BGP peer to BGP speaker matching destination TCP port 179
        selector = buildSelector(tcpProtocol,
                ipTwo,
                ipOne,
                null,
                BGP_PORT);

        key = buildKey(ipTwo, ipOne, SUFFIX_DST);

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .filteredIngressPoint(new FilteredConnectPoint(portTwo))
                .filteredEgressPoint(new FilteredConnectPoint(portOne))
                .priority(PRIORITY_OFFSET)
                .build());

        // ICMP path from BGP speaker to BGP peer
        selector = buildSelector(icmpProtocol,
                ipOne,
                ipTwo,
                null,
                null);

        key = buildKey(ipOne, ipTwo, SUFFIX_ICMP);

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .filteredIngressPoint(new FilteredConnectPoint(portOne))
                .filteredEgressPoint(new FilteredConnectPoint(portTwo))
                .priority(PRIORITY_OFFSET)
                .build());

        // ICMP path from BGP peer to BGP speaker
        selector = buildSelector(icmpProtocol,
                ipTwo,
                ipOne,
                null,
                null);

        key = buildKey(ipTwo, ipOne, SUFFIX_ICMP);

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector)
                .treatment(treatment)
                .filteredIngressPoint(new FilteredConnectPoint(portTwo))
                .filteredEgressPoint(new FilteredConnectPoint(portOne))
                .priority(PRIORITY_OFFSET)
                .build());

        return intents;
    }

    /**
     * Builds a traffic selector based on the set of input parameters.
     *
     * @param ipProto IP protocol
     * @param srcIp source IP address
     * @param dstIp destination IP address
     * @param srcTcpPort source TCP port, or null if shouldn't be set
     * @param dstTcpPort destination TCP port, or null if shouldn't be set
     * @return the new traffic selector
     */
    private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
                                          IpAddress dstIp, Short srcTcpPort,
                                          Short dstTcpPort) {
        TrafficSelector.Builder builder = DefaultTrafficSelector.builder().matchIPProtocol(ipProto);

        if (dstIp.isIp4()) {
            builder.matchEthType(Ethernet.TYPE_IPV4)
                    .matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
                    .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
        } else {
            builder.matchEthType(Ethernet.TYPE_IPV6)
                    .matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
                    .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
        }

        if (srcTcpPort != null) {
            builder.matchTcpSrc(TpPort.tpPort(srcTcpPort));
        }

        if (dstTcpPort != null) {
            builder.matchTcpDst(TpPort.tpPort(dstTcpPort));
        }

        return builder.build();
    }

    /**
     * Builds an intent Key for a point-to-point intent based off the source
     * and destination IP address, as well as a suffix String to distinguish
     * between different types of intents between the same source and
     * destination.
     *
     * @param srcIp source IP address
     * @param dstIp destination IP address
     * @param suffix suffix string
     * @return intent key
     */
    private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
        String keyString = new StringBuilder()
                .append(srcIp.toString())
                .append("-")
                .append(dstIp.toString())
                .append("-")
                .append(suffix)
                .toString();

        return Key.of(keyString, appId);
    }

    @Override
    public void setUpL2(Peer peer) {

        // First update all the previous existing intents. Update ingress points.

        if (!castorStore.getLayer2Intents().isEmpty()) {
            updateExistingL2Intents(peer);
        }

        Set<FilteredConnectPoint> ingressPorts = new HashSet<>();
        ConnectPoint egressPort = ConnectPoint.deviceConnectPoint(peer.getPort());

        for (Peer inPeer : castorStore.getAllPeers()) {
            if (!inPeer.getName().equals(peer.getName())) {
                ingressPorts.add(new FilteredConnectPoint(ConnectPoint.deviceConnectPoint(inPeer.getPort())));
            }
        }
        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
        MacAddress macAddress = castorStore.getAddressMap().get(IpAddress.valueOf(peer.getIpAddress()));
        selector.matchEthDst(macAddress);
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
        Key key = Key.of(peer.getIpAddress(), appId);

        MultiPointToSinglePointIntent intent = MultiPointToSinglePointIntent.builder()
                .appId(appId)
                .key(key)
                .selector(selector.build())
                .treatment(treatment)
                .filteredIngressPoints(ingressPorts)
                .filteredEgressPoint(new FilteredConnectPoint(egressPort))
                .priority(FLOW_PRIORITY)
                .build();
        intentSynchronizer.submit(intent);
        castorStore.storeLayer2Intent(peer.getIpAddress(), intent);
        castorStore.removeCustomer(peer);
        peer.setL2(true);
        castorStore.storeCustomer(peer);
    }

    /**
     * Updates the existing layer 2 flows. Whenever a new Peer is added, it is also
     * added as the ingress point to the existing layer two flows.
     *
     * @param peer The Peer being added.
     */
    private void updateExistingL2Intents(Peer peer) {

        Collection<MultiPointToSinglePointIntent> oldIntents = castorStore.getLayer2Intents().values();

        for (MultiPointToSinglePointIntent oldIntent : oldIntents) {

            Set<FilteredConnectPoint> ingressPoints = oldIntent.filteredIngressPoints();
            ConnectPoint egressPoint = oldIntent.egressPoint();
            if (ingressPoints.add(new FilteredConnectPoint(ConnectPoint.deviceConnectPoint(peer.getPort())))) {

                MultiPointToSinglePointIntent updatedMp2pIntent =
                        MultiPointToSinglePointIntent.builder()
                                .appId(appId)
                                .key(oldIntent.key())
                                .selector(oldIntent.selector())
                                .treatment(oldIntent.treatment())
                                .filteredIngressPoints(ingressPoints)
                                .filteredEgressPoint(new FilteredConnectPoint(egressPoint))
                                .priority(oldIntent.priority())
                                .build();

                //layer2Intents.put(peer.getIpAddress(), updatedMp2pIntent);
                castorStore.storeLayer2Intent(peer.getIpAddress(), updatedMp2pIntent);
                intentSynchronizer.submit(updatedMp2pIntent);
            }
        }
    }

    @Override
    public void deletePeer(Peer peer) {

        if (castorStore.getCustomers().contains(peer)) {

            deletel3(peer);

            for (Peer customer : castorStore.getCustomers()) {
                if (customer.getIpAddress().equals(peer.getIpAddress()) && customer.getl2Status()) {
                    deleteL2(customer);
                    updateL2AfterDeletion(customer);
                }
            }
            castorStore.removeCustomer(peer);
        }
    }

    /**
     * Delete all the flows between the Peer being deleted and the Route Servers
     * to kill the BGP sessions. It uses the keys to retrive the previous intents
     * and withdraw them.
     *
     * @param peer The Peer being deleted.
     */
    private void deletel3(Peer peer) {

        List<Key> keys = new LinkedList<>();
        IpAddress ipTwo = IpAddress.valueOf(peer.getIpAddress());

        for (Peer server : castorStore.getServers()) {
            IpAddress ipOne = IpAddress.valueOf(server.getIpAddress());
            keys.add(buildKey(ipOne, ipTwo, SUFFIX_SRC));
            keys.add(buildKey(ipTwo, ipOne, SUFFIX_DST));
            keys.add(buildKey(ipOne, ipTwo, SUFFIX_ICMP));
            keys.add(buildKey(ipTwo, ipOne, SUFFIX_ICMP));
        }
        for (Key keyDel : keys) {

            PointToPointIntent intent = castorStore.getPeerIntents().get(keyDel);
            intentSynchronizer.withdraw(intent);
            castorStore.removePeerIntent(keyDel);
        }
    }

    /**
     * Deletes the layer two flows for the peer being deleted.
     *
     * @param peer The Peer being deleted.
     */
    private void deleteL2(Peer peer) {
        intentSynchronizer.withdraw(castorStore.getLayer2Intents().get(peer.getIpAddress()));
        castorStore.removeLayer2Intent(peer.getIpAddress());
    }

    /**
     * Updates all the layer 2 flows after successful deletion of a Peer.
     * The Peer being deleted is removed from the ingress points of all
     * other flows.
     *
     * @param peer The Peer being deleted.
     */
    private void updateL2AfterDeletion(Peer peer) {
        Collection<MultiPointToSinglePointIntent> oldIntents = castorStore.getLayer2Intents().values();
        Map<String, MultiPointToSinglePointIntent> intents = new HashMap<>();

        for (MultiPointToSinglePointIntent oldIntent : oldIntents) {

            Set<FilteredConnectPoint> ingressPoints = oldIntent.filteredIngressPoints();
            FilteredConnectPoint egressPoint = oldIntent.filteredEgressPoint();
            if (ingressPoints.remove(new FilteredConnectPoint(ConnectPoint.deviceConnectPoint(peer.getPort())))) {

                MultiPointToSinglePointIntent updatedMp2pIntent =
                        MultiPointToSinglePointIntent.builder()
                                .appId(appId)
                                .key(oldIntent.key())
                                .selector(oldIntent.selector())
                                .treatment(oldIntent.treatment())
                                .filteredIngressPoints(ingressPoints)
                                .filteredEgressPoint(egressPoint)
                                .priority(oldIntent.priority())
                                .build();

                intents.put(peer.getIpAddress(), updatedMp2pIntent);
                intentSynchronizer.submit(updatedMp2pIntent);
            }
        }
        for (String key : intents.keySet()) {
            castorStore.storeLayer2Intent(key, intents.get(key));
        }
    }
}
