/*
 * 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.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)
                .ingressPoint(portOne)
                .egressPoint(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)
                .ingressPoint(portTwo)
                .egressPoint(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)
                .ingressPoint(portOne)
                .egressPoint(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)
                .ingressPoint(portTwo)
                .egressPoint(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<ConnectPoint> ingressPorts = new HashSet<>();
        ConnectPoint egressPort = ConnectPoint.deviceConnectPoint(peer.getPort());

        for (Peer inPeer : castorStore.getAllPeers()) {
            if (!inPeer.getName().equals(peer.getName())) {
                ingressPorts.add(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)
                .ingressPoints(ingressPorts)
                .egressPoint(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<ConnectPoint> ingressPoints = oldIntent.ingressPoints();
            ConnectPoint egressPoint = oldIntent.egressPoint();
            if (ingressPoints.add(ConnectPoint.deviceConnectPoint(peer.getPort()))) {

                MultiPointToSinglePointIntent updatedMp2pIntent =
                        MultiPointToSinglePointIntent.builder()
                                .appId(appId)
                                .key(oldIntent.key())
                                .selector(oldIntent.selector())
                                .treatment(oldIntent.treatment())
                                .ingressPoints(ingressPoints)
                                .egressPoint(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<ConnectPoint> ingressPoints = oldIntent.ingressPoints();
            ConnectPoint egressPoint = oldIntent.egressPoint();
            if (ingressPoints.remove(ConnectPoint.deviceConnectPoint(peer.getPort()))) {

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

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