/*
 * Copyright 2015-present 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.routing.bgp;

import org.onlab.packet.IpPrefix;
import org.onosproject.incubator.net.routing.Route;
import org.onosproject.routing.RouteUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.LinkedList;

/**
 * Class to receive and process the BGP routes from each BGP Session/Peer.
 */
class BgpRouteSelector {
    private static final Logger log =
        LoggerFactory.getLogger(BgpRouteSelector.class);

    private BgpSessionManager bgpSessionManager;

    /**
     * Constructor.
     *
     * @param bgpSessionManager the BGP Session Manager to use
     */
    BgpRouteSelector(BgpSessionManager bgpSessionManager) {
        this.bgpSessionManager = bgpSessionManager;
    }

    /**
     * Processes route entry updates: added/updated and deleted route
     * entries.
     *
     * @param addedBgpRouteEntries the added/updated route entries to process
     * @param deletedBgpRouteEntries the deleted route entries to process
     */
    synchronized void routeUpdates(
                        Collection<BgpRouteEntry> addedBgpRouteEntries,
                        Collection<BgpRouteEntry> deletedBgpRouteEntries) {

        Collection<Route> updates = new LinkedList<>();
        Collection<Route> withdraws = new LinkedList<>();

        RouteUpdate routeUpdate;

        if (bgpSessionManager.isShutdown()) {
            return;         // Ignore any leftover updates if shutdown
        }
        // Process the deleted route entries
        for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) {
            routeUpdate = processDeletedRoute(bgpRouteEntry);
            convertRouteUpdateToRoute(routeUpdate, updates, withdraws);
        }

        // Process the added/updated route entries
        for (BgpRouteEntry bgpRouteEntry : addedBgpRouteEntries) {
            routeUpdate = processAddedRoute(bgpRouteEntry);
            convertRouteUpdateToRoute(routeUpdate, updates, withdraws);
        }

        bgpSessionManager.withdraw(withdraws);
        bgpSessionManager.update(updates);
    }

    private void convertRouteUpdateToRoute(RouteUpdate routeUpdate,
                                           Collection<Route> updates,
                                           Collection<Route> withdraws) {
        if (routeUpdate != null) {
            Route route = new Route(Route.Source.BGP, routeUpdate.routeEntry().prefix(),
                    routeUpdate.routeEntry().nextHop());
            if (routeUpdate.type().equals(RouteUpdate.Type.UPDATE)) {
                updates.add(route);
            } else if (routeUpdate.type().equals(RouteUpdate.Type.DELETE)) {
                withdraws.add(route);
            }
        }
    }

    /**
     * Processes an added/updated route entry.
     *
     * @param bgpRouteEntry the added/updated route entry
     * @return the result route update that should be forwarded to the
     * Route Listener, or null if no route update should be forwarded
     */
    private RouteUpdate processAddedRoute(BgpRouteEntry bgpRouteEntry) {
        RouteUpdate routeUpdate;
        BgpRouteEntry bestBgpRouteEntry =
            bgpSessionManager.findBgpRoute(bgpRouteEntry.prefix());

        //
        // Install the new route entry if it is better than the
        // current best route.
        //
        if ((bestBgpRouteEntry == null) ||
            bgpRouteEntry.isBetterThan(bestBgpRouteEntry)) {
            bgpSessionManager.addBgpRoute(bgpRouteEntry);
            routeUpdate =
                new RouteUpdate(RouteUpdate.Type.UPDATE, bgpRouteEntry);
            return routeUpdate;
        }

        //
        // 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 null;            // Nothing to do
        }

        // 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
        bgpSessionManager.addBgpRoute(bestBgpRouteEntry);
        routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                      bestBgpRouteEntry);
        return routeUpdate;
    }

    /**
     * Processes a deleted route entry.
     *
     * @param bgpRouteEntry the deleted route entry
     * @return the result route update that should be forwarded to the
     * Route Listener, or null if no route update should be forwarded
     */
    private RouteUpdate processDeletedRoute(BgpRouteEntry bgpRouteEntry) {
        RouteUpdate routeUpdate;
        BgpRouteEntry bestBgpRouteEntry =
            bgpSessionManager.findBgpRoute(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 null;            // Nothing to do
        }

        //
        // Find the next best route
        //
        bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix());
        if (bestBgpRouteEntry != null) {
            // Install the next best route
            bgpSessionManager.addBgpRoute(bestBgpRouteEntry);
            routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE,
                                          bestBgpRouteEntry);
            return routeUpdate;
        }

        //
        // No route found. Remove the route entry
        //
        bgpSessionManager.removeBgpRoute(bgpRouteEntry.prefix());
        routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE, bgpRouteEntry);
        return 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 : bgpSessionManager.getBgpSessions()) {
            BgpRouteEntry route = bgpSession.findBgpRoute(prefix);
            if (route == null) {
                continue;
            }
            if ((bestRoute == null) || route.isBetterThan(bestRoute)) {
                bestRoute = route;
            }
        }
        return bestRoute;
    }
}
