/*
 * 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.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);
        }
    }
}
