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

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.onlab.util.Tools.groupedThreads;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;

/**
 * Class for handling the BGP peer sessions.
 * There is one instance per each BGP peer session.
 */
public class BgpSession extends SimpleChannelHandler {
    private static final Logger log =
        LoggerFactory.getLogger(BgpSession.class);

    private final BgpSessionManager bgpSessionManager;

    // Local flag to indicate the session is closed.
    // It is used to avoid the Netty's asynchronous closing of a channel.
    private boolean isClosed = false;

    // BGP session info: local and remote
    private final BgpSessionInfo localInfo;     // BGP session local info
    private final BgpSessionInfo remoteInfo;    // BGP session remote info

    // Timers state
    private Timer timer = new HashedWheelTimer(groupedThreads("BgpSession", "timer-%d", log));
    private volatile Timeout keepaliveTimeout;  // Periodic KEEPALIVE
    private volatile Timeout sessionTimeout;    // Session timeout

    // BGP RIB-IN routing entries from this peer
    private ConcurrentMap<Ip4Prefix, BgpRouteEntry> bgpRibIn4 =
        new ConcurrentHashMap<>();
    private ConcurrentMap<Ip6Prefix, BgpRouteEntry> bgpRibIn6 =
        new ConcurrentHashMap<>();

    /**
     * Constructor for a given BGP Session Manager.
     *
     * @param bgpSessionManager the BGP Session Manager to use
     */
    BgpSession(BgpSessionManager bgpSessionManager) {
        this.bgpSessionManager = bgpSessionManager;
        this.localInfo = new BgpSessionInfo();
        this.remoteInfo = new BgpSessionInfo();

        // NOTE: We support only BGP4
        this.localInfo.setBgpVersion(BgpConstants.BGP_VERSION);
    }

    /**
     * Gets the BGP Session Manager.
     *
     * @return the BGP Session Manager
     */
    BgpSessionManager getBgpSessionManager() {
        return bgpSessionManager;
    }

    /**
     * Gets the BGP Session local information.
     *
     * @return the BGP Session local information.
     */
    public BgpSessionInfo localInfo() {
        return localInfo;
    }

    /**
     * Gets the BGP Session remote information.
     *
     * @return the BGP Session remote information.
     */
    public BgpSessionInfo remoteInfo() {
        return remoteInfo;
    }

    /**
     * Gets the BGP Multiprotocol Extensions for the session.
     *
     * @return true if the BGP Multiprotocol Extensions are enabled for the
     * session, otherwise false
     */
    public boolean mpExtensions() {
        return remoteInfo.mpExtensions() && localInfo.mpExtensions();
    }

    /**
     * Gets the BGP session 4 octet AS path capability.
     *
     * @return true when the BGP session is 4 octet AS path capable
     */
    public boolean isAs4OctetCapable() {
        return remoteInfo.as4OctetCapability() &&
            localInfo.as4OctetCapability();
    }

    /**
     * Gets the IPv4 BGP RIB-IN routing entries.
     *
     * @return the IPv4 BGP RIB-IN routing entries
     */
    public Collection<BgpRouteEntry> getBgpRibIn4() {
        return bgpRibIn4.values();
    }

    /**
     * Gets the IPv6 BGP RIB-IN routing entries.
     *
     * @return the IPv6 BGP RIB-IN routing entries
     */
    public Collection<BgpRouteEntry> getBgpRibIn6() {
        return bgpRibIn6.values();
    }

    /**
     * Finds an IPv4 BGP routing entry for a prefix in the IPv4 BGP RIB-IN.
     *
     * @param prefix the IPv4 prefix of the route to search for
     * @return the IPv4 BGP routing entry if found, otherwise null
     */
    public BgpRouteEntry findBgpRoute(Ip4Prefix prefix) {
        return bgpRibIn4.get(prefix);
    }

    /**
     * Finds an IPv6 BGP routing entry for a prefix in the IPv6 BGP RIB-IN.
     *
     * @param prefix the IPv6 prefix of the route to search for
     * @return the IPv6 BGP routing entry if found, otherwise null
     */
    public BgpRouteEntry findBgpRoute(Ip6Prefix prefix) {
        return bgpRibIn6.get(prefix);
    }

    /**
     * Finds a BGP routing entry for a prefix in the BGP RIB-IN. The prefix
     * can be either IPv4 or IPv6.
     *
     * @param prefix the IP prefix of the route to search for
     * @return the BGP routing entry if found, otherwise null
     */
    public BgpRouteEntry findBgpRoute(IpPrefix prefix) {
        if (prefix.isIp4()) {
            // IPv4 prefix
            Ip4Prefix ip4Prefix = prefix.getIp4Prefix();
            return bgpRibIn4.get(ip4Prefix);
        }

        // IPv6 prefix
        Ip6Prefix ip6Prefix = prefix.getIp6Prefix();
        return bgpRibIn6.get(ip6Prefix);
    }

    /**
     * Adds a BGP route. The route can be either IPv4 or IPv6.
     *
     * @param bgpRouteEntry the BGP route entry to use
     */
    void addBgpRoute(BgpRouteEntry bgpRouteEntry) {
        if (bgpRouteEntry.isIp4()) {
            // IPv4 route
            Ip4Prefix ip4Prefix = bgpRouteEntry.prefix().getIp4Prefix();
            bgpRibIn4.put(ip4Prefix, bgpRouteEntry);
        } else {
            // IPv6 route
            Ip6Prefix ip6Prefix = bgpRouteEntry.prefix().getIp6Prefix();
            bgpRibIn6.put(ip6Prefix, bgpRouteEntry);
        }
    }

    /**
     * Removes an IPv4 BGP route for a prefix.
     *
     * @param prefix the prefix to use
     * @return true if the route was found and removed, otherwise false
     */
    boolean removeBgpRoute(Ip4Prefix prefix) {
        return (bgpRibIn4.remove(prefix) != null);
    }

    /**
     * Removes an IPv6 BGP route for a prefix.
     *
     * @param prefix the prefix to use
     * @return true if the route was found and removed, otherwise false
     */
    boolean removeBgpRoute(Ip6Prefix prefix) {
        return (bgpRibIn6.remove(prefix) != null);
    }

    /**
     * Removes a BGP route for a prefix. The prefix can be either IPv4 or IPv6.
     *
     * @param prefix the prefix to use
     * @return true if the route was found and removed, otherwise false
     */
    boolean removeBgpRoute(IpPrefix prefix) {
        if (prefix.isIp4()) {
            return (bgpRibIn4.remove(prefix.getIp4Prefix()) != null);   // IPv4
        }
        return (bgpRibIn6.remove(prefix.getIp6Prefix()) != null);       // IPv6
    }

    /**
     * Tests whether the session is closed.
     * <p>
     * NOTE: We use this method to avoid the Netty's asynchronous closing
     * of a channel.
     * </p>
     * @return true if the session is closed
     */
    boolean isClosed() {
        return isClosed;
    }

    /**
     * Closes the session.
     *
     * @param ctx the Channel Handler Context
     */
    void closeSession(ChannelHandlerContext ctx) {
        timer.stop();
        closeChannel(ctx);
    }

    /**
     * Closes the Netty channel.
     *
     * @param ctx the Channel Handler Context
     */
    void closeChannel(ChannelHandlerContext ctx) {
        isClosed = true;
        ctx.getChannel().close();
    }

    @Override
    public void channelOpen(ChannelHandlerContext ctx,
                            ChannelStateEvent channelEvent) {
        bgpSessionManager.addSessionChannel(channelEvent.getChannel());
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx,
                              ChannelStateEvent channelEvent) {
        bgpSessionManager.removeSessionChannel(channelEvent.getChannel());
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx,
                                 ChannelStateEvent channelEvent) {
        localInfo.setAddress(ctx.getChannel().getLocalAddress());
        remoteInfo.setAddress(ctx.getChannel().getRemoteAddress());

        // Assign the local and remote IPv4 addresses
        InetAddress inetAddr;
        if (localInfo.address() instanceof InetSocketAddress) {
            inetAddr = ((InetSocketAddress) localInfo.address()).getAddress();
            localInfo.setIp4Address(Ip4Address.valueOf(inetAddr.getAddress()));
        }
        if (remoteInfo.address() instanceof InetSocketAddress) {
            inetAddr = ((InetSocketAddress) remoteInfo.address()).getAddress();
            remoteInfo.setIp4Address(Ip4Address.valueOf(inetAddr.getAddress()));
        }

        log.debug("BGP Session Connected from {} on {}",
                  remoteInfo.address(), localInfo.address());
        if (!bgpSessionManager.peerConnected(this)) {
            log.debug("Cannot setup BGP Session Connection from {}. Closing...",
                      remoteInfo.address());
            ctx.getChannel().close();
        }

        //
        // Assign the local BGP ID
        // NOTE: This should be configuration-based
        //
        localInfo.setBgpId(bgpSessionManager.getMyBgpId());
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx,
                                    ChannelStateEvent channelEvent) {
        log.debug("BGP Session Disconnected from {} on {}",
                  ctx.getChannel().getRemoteAddress(),
                  ctx.getChannel().getLocalAddress());
        processChannelDisconnected();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        log.debug("BGP Session Exception Caught from {} on {}: {}",
                  ctx.getChannel().getRemoteAddress(),
                  ctx.getChannel().getLocalAddress(),
                  e);
        log.debug("Exception:", e.getCause());
        processChannelDisconnected();
    }

    /**
     * Processes the channel being disconnected.
     */
    private void processChannelDisconnected() {
        //
        // Withdraw the routes advertised by this BGP peer
        //
        // NOTE: We must initialize the RIB-IN before propagating the withdraws
        // for further processing. Otherwise, the BGP Decision Process
        // will use those routes again.
        //
        Collection<BgpRouteEntry> deletedRoutes4 = bgpRibIn4.values();
        Collection<BgpRouteEntry> deletedRoutes6 = bgpRibIn6.values();
        bgpRibIn4 = new ConcurrentHashMap<>();
        bgpRibIn6 = new ConcurrentHashMap<>();

        // Push the updates to the BGP Merged RIB
        BgpRouteSelector bgpRouteSelector =
            bgpSessionManager.getBgpRouteSelector();
        Collection<BgpRouteEntry> addedRoutes = Collections.emptyList();
        bgpRouteSelector.routeUpdates(addedRoutes, deletedRoutes4);
        bgpRouteSelector.routeUpdates(addedRoutes, deletedRoutes6);

        bgpSessionManager.peerDisconnected(this);
    }

    /**
     * Restarts the BGP KeepaliveTimer.
     *
     * @param ctx the Channel Handler Context to use
     */
    void restartKeepaliveTimer(ChannelHandlerContext ctx) {
        long localKeepaliveInterval = 0;

        //
        // Compute the local Keepalive interval
        //
        if (localInfo.holdtime() != 0) {
            localKeepaliveInterval = Math.max(localInfo.holdtime() /
                         BgpConstants.BGP_KEEPALIVE_PER_HOLD_INTERVAL,
                         BgpConstants.BGP_KEEPALIVE_MIN_INTERVAL);
        }

        // Restart the Keepalive timer
        if (localKeepaliveInterval == 0) {
            return;                 // Nothing to do
        }
        keepaliveTimeout = timer.newTimeout(new TransmitKeepaliveTask(ctx),
                                            localKeepaliveInterval,
                                            TimeUnit.SECONDS);
    }

    /**
     * Task class for transmitting KEEPALIVE messages.
     */
    private final class TransmitKeepaliveTask implements TimerTask {
        private final ChannelHandlerContext ctx;

        /**
         * Constructor for given Channel Handler Context.
         *
         * @param ctx the Channel Handler Context to use
         */
        TransmitKeepaliveTask(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }

        @Override
        public void run(Timeout timeout) throws Exception {
            if (timeout.isCancelled()) {
                return;
            }
            if (!ctx.getChannel().isOpen()) {
                return;
            }

            // Transmit the KEEPALIVE
            ChannelBuffer txMessage = BgpKeepalive.prepareBgpKeepalive();
            ctx.getChannel().write(txMessage);

            // Restart the KEEPALIVE timer
            restartKeepaliveTimer(ctx);
        }
    }

    /**
     * Restarts the BGP Session Timeout Timer.
     *
     * @param ctx the Channel Handler Context to use
     */
    void restartSessionTimeoutTimer(ChannelHandlerContext ctx) {
        if (remoteInfo.holdtime() == 0) {
            return;                 // Nothing to do
        }
        if (sessionTimeout != null) {
            sessionTimeout.cancel();
        }
        sessionTimeout = timer.newTimeout(new SessionTimeoutTask(ctx),
                                          remoteInfo.holdtime(),
                                          TimeUnit.SECONDS);
    }

    /**
     * Task class for BGP Session timeout.
     */
    private final class SessionTimeoutTask implements TimerTask {
        private final ChannelHandlerContext ctx;

        /**
         * Constructor for given Channel Handler Context.
         *
         * @param ctx the Channel Handler Context to use
         */
        SessionTimeoutTask(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }

        @Override
        public void run(Timeout timeout) throws Exception {
            if (timeout.isCancelled()) {
                return;
            }
            if (!ctx.getChannel().isOpen()) {
                return;
            }

            log.debug("BGP Session Timeout: peer {}", remoteInfo.address());
            //
            // ERROR: Invalid Optional Parameter Length field: Unspecific
            //
            // Send NOTIFICATION and close the connection
            int errorCode = BgpConstants.Notifications.HoldTimerExpired.ERROR_CODE;
            int errorSubcode = BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC;
            ChannelBuffer txMessage =
                BgpNotification.prepareBgpNotification(errorCode, errorSubcode,
                                                       null);
            ctx.getChannel().write(txMessage);
            closeChannel(ctx);
        }
    }
}
