/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.onlab.onos.sdnip.bgp;

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

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelException;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.onlab.onos.sdnip.RouteListener;
import org.onlab.onos.sdnip.RouteUpdate;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * BGP Session Manager class.
 */
public class BgpSessionManager {
    private static final Logger log =
        LoggerFactory.getLogger(BgpSessionManager.class);
    private Channel serverChannel;     // Listener for incoming BGP connections
    private ConcurrentMap<SocketAddress, BgpSession> bgpSessions =
        new ConcurrentHashMap<>();
    private IpAddress myBgpId;         // Same BGP ID for all peers

    private BgpRouteSelector bgpRouteSelector = new BgpRouteSelector();
    private ConcurrentMap<IpPrefix, BgpRouteEntry> bgpRoutes =
        new ConcurrentHashMap<>();

    private final RouteListener routeListener;

    /**
     * Constructor for given route listener.
     *
     * @param routeListener the route listener to use
     */
    public BgpSessionManager(RouteListener routeListener) {
        this.routeListener = checkNotNull(routeListener);
    }

    /**
     * Gets the BGP sessions.
     *
     * @return the BGP sessions
     */
    public Collection<BgpSession> getBgpSessions() {
        return bgpSessions.values();
    }

    /**
     * Gets the BGP routes.
     *
     * @return the BGP routes
     */
    public Collection<BgpRouteEntry> getBgpRoutes() {
        return bgpRoutes.values();
    }

    /**
     * Processes the connection from a BGP peer.
     *
     * @param bgpSession the BGP session for the peer
     * @return true if the connection can be established, otherwise false
     */
    boolean peerConnected(BgpSession bgpSession) {

        // Test whether there is already a session from the same remote
        if (bgpSessions.get(bgpSession.getRemoteAddress()) != null) {
            return false;               // Duplicate BGP session
        }
        bgpSessions.put(bgpSession.getRemoteAddress(), bgpSession);

        //
        // If the first connection, set my BGP ID to the local address
        // of the socket.
        //
        if (bgpSession.getLocalAddress() instanceof InetSocketAddress) {
            InetAddress inetAddr =
                ((InetSocketAddress) bgpSession.getLocalAddress()).getAddress();
            IpAddress ip4Address = IpAddress.valueOf(inetAddr.getAddress());
            updateMyBgpId(ip4Address);
        }
        return true;
    }

    /**
     * Processes the disconnection from a BGP peer.
     *
     * @param bgpSession the BGP session for the peer
     */
    void peerDisconnected(BgpSession bgpSession) {
        bgpSessions.remove(bgpSession.getRemoteAddress());
    }

    /**
     * Conditionally updates the local BGP ID if it wasn't set already.
     * <p/>
     * NOTE: A BGP instance should use same BGP ID across all BGP sessions.
     *
     * @param ip4Address the IPv4 address to use as BGP ID
     */
    private synchronized void updateMyBgpId(IpAddress ip4Address) {
        if (myBgpId == null) {
            myBgpId = ip4Address;
            log.debug("BGP: My BGP ID is {}", myBgpId);
        }
    }

    /**
     * Gets the local BGP Identifier as an IPv4 address.
     *
     * @return the local BGP Identifier as an IPv4 address
     */
    IpAddress getMyBgpId() {
        return myBgpId;
    }

    /**
     * Gets the BGP Route Selector.
     *
     * @return the BGP Route Selector
     */
    BgpRouteSelector getBgpRouteSelector() {
        return bgpRouteSelector;
    }

    /**
     * Starts up BGP Session Manager operation.
     *
     * @param listenPortNumber the port number to listen on. By default
     * it should be BgpConstants.BGP_PORT (179)
     */
    public void startUp(int listenPortNumber) {
        log.debug("BGP Session Manager startUp()");

        ChannelFactory channelFactory =
            new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
                                              Executors.newCachedThreadPool());
        ChannelPipelineFactory pipelineFactory = new ChannelPipelineFactory() {
                @Override
                public ChannelPipeline getPipeline() throws Exception {
                    // Allocate a new session per connection
                    BgpSession bgpSessionHandler =
                        new BgpSession(BgpSessionManager.this);
                    BgpFrameDecoder bgpFrameDecoder =
                        new BgpFrameDecoder(bgpSessionHandler);

                    // Setup the processing pipeline
                    ChannelPipeline pipeline = Channels.pipeline();
                    pipeline.addLast("BgpFrameDecoder", bgpFrameDecoder);
                    pipeline.addLast("BgpSession", bgpSessionHandler);
                    return pipeline;
                }
            };
        InetSocketAddress listenAddress =
            new InetSocketAddress(listenPortNumber);

        ServerBootstrap serverBootstrap = new ServerBootstrap(channelFactory);
        // serverBootstrap.setOptions("reuseAddr", true);
        serverBootstrap.setOption("child.keepAlive", true);
        serverBootstrap.setOption("child.tcpNoDelay", true);
        serverBootstrap.setPipelineFactory(pipelineFactory);
        try {
            serverChannel = serverBootstrap.bind(listenAddress);
        } catch (ChannelException e) {
            log.debug("Exception binding to BGP port {}: ",
                      listenAddress.getPort(), e);
        }
    }

    /**
     * Shuts down the BGP Session Manager operation.
     */
    public void shutDown() {
        // TODO: Complete the implementation: remove routes, etc.
        if (serverChannel != null) {
            serverChannel.close();
        }
    }

    /**
     * Class to receive and process the BGP routes from each BGP Session/Peer.
     */
    class BgpRouteSelector {
        /**
         * Processes route entry updates: added/updated and deleted route
         * entries.
         *
         * @param bgpSession the BGP session the route entry updates were
         * received on
         * @param addedBgpRouteEntries the added/updated route entries to
         * process
         * @param deletedBgpRouteEntries the deleted route entries to process
         */
        synchronized void routeUpdates(BgpSession bgpSession,
                        Collection<BgpRouteEntry> addedBgpRouteEntries,
                        Collection<BgpRouteEntry> deletedBgpRouteEntries) {
            //
            // TODO: Merge the updates from different BGP Peers,
            // by choosing the best route.
            //

            // Process the deleted route entries
            for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) {
                processDeletedRoute(bgpSession, bgpRouteEntry);
            }

            // Process the added/updated route entries
            for (BgpRouteEntry bgpRouteEntry : addedBgpRouteEntries) {
                processAddedRoute(bgpSession, bgpRouteEntry);
            }
        }

        /**
         * Processes an added/updated route entry.
         *
         * @param bgpSession the BGP session the route entry update was
         * received on
         * @param bgpRouteEntry the added/updated route entry
         */
        private void processAddedRoute(BgpSession bgpSession,
                                       BgpRouteEntry bgpRouteEntry) {
            RouteUpdate routeUpdate;
            BgpRouteEntry bestBgpRouteEntry =
                bgpRoutes.get(bgpRouteEntry.prefix());

            //
            // Install the new route entry if it is better than the
            // current best route.
            //
            if ((bestBgpRouteEntry == null) ||
                bgpRouteEntry.isBetterThan(bestBgpRouteEntry)) {
                bgpRoutes.put(bgpRouteEntry.prefix(), bgpRouteEntry);
                routeUpdate =
                    new RouteUpdate(RouteUpdate.Type.UPDATE, bgpRouteEntry);
                // Forward the result route updates to the Route Listener
                routeListener.update(routeUpdate);
                return;
            }

            //
            // If the route entry arrived on the same BGP Session as
            // the current best route, then elect the next best route
            // and install it.
            //
            if (bestBgpRouteEntry.getBgpSession() !=
                bgpRouteEntry.getBgpSession()) {
                return;
            }

            // Find the next best route
            bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix());
            if (bestBgpRouteEntry == null) {
                //
                // TODO: Shouldn't happen. Install the new route as a
                // pre-caution.
                //
                log.debug("BGP next best route for prefix {} is missing. " +
                          "Adding the route that is currently processed.",
                          bgpRouteEntry.prefix());
                bestBgpRouteEntry = bgpRouteEntry;
            }
            // Install the next best route
            bgpRoutes.put(bestBgpRouteEntry.prefix(), bestBgpRouteEntry);
            routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                          bestBgpRouteEntry);
            // Forward the result route updates to the Route Listener
            routeListener.update(routeUpdate);
        }

        /**
         * Processes a deleted route entry.
         *
         * @param bgpSession the BGP session the route entry update was
         * received on
         * @param bgpRouteEntry the deleted route entry
         */
        private void processDeletedRoute(BgpSession bgpSession,
                                         BgpRouteEntry bgpRouteEntry) {
            RouteUpdate routeUpdate;
            BgpRouteEntry bestBgpRouteEntry =
                bgpRoutes.get(bgpRouteEntry.prefix());

            //
            // Remove the route entry only if it was the best one.
            // Install the the next best route if it exists.
            //
            // NOTE: We intentionally use "==" instead of method equals(),
            // because we need to check whether this is same object.
            //
            if (bgpRouteEntry != bestBgpRouteEntry) {
                return;         // Nothing to do
            }

            //
            // Find the next best route
            //
            bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix());
            if (bestBgpRouteEntry != null) {
                // Install the next best route
                bgpRoutes.put(bestBgpRouteEntry.prefix(),
                              bestBgpRouteEntry);
                routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                              bestBgpRouteEntry);
                // Forward the result route updates to the Route Listener
                routeListener.update(routeUpdate);
                return;
            }

            //
            // No route found. Remove the route entry
            //
            bgpRoutes.remove(bgpRouteEntry.prefix());
            routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE,
                                          bgpRouteEntry);
            // Forward the result route updates to the Route Listener
            routeListener.update(routeUpdate);
        }

        /**
         * Finds the best route entry among all BGP Sessions.
         *
         * @param prefix the prefix of the route
         * @return the best route if found, otherwise null
         */
        private BgpRouteEntry findBestBgpRoute(IpPrefix prefix) {
            BgpRouteEntry bestRoute = null;

            // Iterate across all BGP Sessions and select the best route
            for (BgpSession bgpSession : bgpSessions.values()) {
                BgpRouteEntry route = bgpSession.findBgpRouteEntry(prefix);
                if (route == null) {
                    continue;
                }
                if ((bestRoute == null) || route.isBetterThan(bestRoute)) {
                    bestRoute = route;
                }
            }
            return bestRoute;
        }
    }
}
