/*
 * Copyright 2014-2015 Open Networking Laboratory
 *
 * 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.sdnip;

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.onosproject.core.ApplicationId;
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.host.InterfaceIpAddress;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.routing.config.BgpPeer;
import org.onosproject.routing.config.BgpSpeaker;
import org.onosproject.routing.config.Interface;
import org.onosproject.routing.config.InterfaceAddress;
import org.onosproject.routing.config.RoutingConfigurationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Manages the connectivity requirements between peers.
 */
public class PeerConnectivityManager {
    private static final int PRIORITY_OFFSET = 1000;

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

    private static final short BGP_PORT = 179;

    private final IntentSynchronizer intentSynchronizer;
    private final RoutingConfigurationService configService;

    private final ApplicationId appId;

    /**
     * Creates a new PeerConnectivityManager.
     *
     * @param appId              the application ID
     * @param intentSynchronizer the intent synchronizer
     * @param configService      the SDN-IP config service
     */
    public PeerConnectivityManager(ApplicationId appId,
                                   IntentSynchronizer intentSynchronizer,
                                   RoutingConfigurationService configService) {
        this.appId = appId;
        this.intentSynchronizer = intentSynchronizer;
        this.configService = configService;
    }

    /**
     * Starts the peer connectivity manager.
     */
    public void start() {
        if (configService.getInterfaces().isEmpty()) {
            log.warn("No interfaces found in configuration file");
        }

        if (configService.getBgpPeers().isEmpty()) {
            log.warn("No BGP peers found in configuration file");
        }

        if (configService.getBgpSpeakers().isEmpty()) {
            log.error("No BGP speakers found in configuration file");
        }

        setUpConnectivity();
    }

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

    /**
     * Sets up paths to establish connectivity between all internal
     * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
     */
    private void setUpConnectivity() {
        List<PointToPointIntent> intents = new ArrayList<>();

        for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
                .values()) {
            log.debug("Start to set up BGP paths for BGP speaker: {}",
                      bgpSpeaker);

            for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {

                log.debug("Start to set up BGP paths between BGP speaker: {} "
                                  + "to BGP peer: {}", bgpSpeaker, bgpPeer);

                intents.addAll(buildPeerIntents(bgpSpeaker, bgpPeer));
            }
        }

        // Submit all the intents.
        intentSynchronizer.submitPeerIntents(intents);
    }

    /**
     * Builds the required intents between a given internal BGP speaker and
     * external BGP peer.
     *
     * @param bgpSpeaker the BGP speaker
     * @param bgpPeer the BGP peer
     * @return the intents to install
     */
    private Collection<PointToPointIntent> buildPeerIntents(
            BgpSpeaker bgpSpeaker,
            BgpPeer bgpPeer) {
        List<PointToPointIntent> intents = new ArrayList<>();

        ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();

        List<InterfaceAddress> interfaceAddresses =
                bgpSpeaker.interfaceAddresses();

        IpAddress bgpdAddress = null;
        for (InterfaceAddress interfaceAddress : interfaceAddresses) {
            Interface peerInterface = configService.getInterface(interfaceAddress.ipAddress());
            if (peerInterface == null) {
                continue;
            }

            for (InterfaceIpAddress interfaceIpAddress : peerInterface.ipAddresses()) {
                // Only add intents where the peer and ONOS's addresses are
                // in the same subnet
                if (interfaceIpAddress.subnetAddress().contains(bgpPeer.ipAddress())) {
                    bgpdAddress = interfaceAddress.ipAddress();
                    break;
                }
            }
            if (bgpdAddress != null) {
                break;
            }
        }
        if (bgpdAddress == null) {
            log.debug("No IP address found for peer {} on interface {}",
                    bgpPeer, bgpPeer.connectPoint());
            return intents;
        }

        IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
        ConnectPoint bgpdPeerConnectPoint = bgpPeer.connectPoint();

        if (bgpdAddress.version() != bgpdPeerAddress.version()) {
            return intents;
        }

        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        TrafficSelector selector;

        byte tcpProtocol;
        byte icmpProtocol;

        if (bgpdAddress.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 destination TCP port 179
        selector = buildSelector(tcpProtocol,
                bgpdAddress,
                bgpdPeerAddress,
                null,
                BGP_PORT);

        int priority = PRIORITY_OFFSET;

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdConnectPoint)
                .egressPoint(bgpdPeerConnectPoint)
                .priority(priority)
                .build());

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

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdConnectPoint)
                .egressPoint(bgpdPeerConnectPoint)
                .priority(priority)
                .build());

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

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdPeerConnectPoint)
                .egressPoint(bgpdConnectPoint)
                .priority(priority)
                .build());

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

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdPeerConnectPoint)
                .egressPoint(bgpdConnectPoint)
                .priority(priority)
                .build());

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

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdConnectPoint)
                .egressPoint(bgpdPeerConnectPoint)
                .priority(priority)
                .build());

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

        intents.add(PointToPointIntent.builder()
                .appId(appId)
                .selector(selector)
                .treatment(treatment)
                .ingressPoint(bgpdPeerConnectPoint)
                .egressPoint(bgpdConnectPoint)
                .priority(priority)
                .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 = null;

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

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

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

        return builder.build();
    }

}
