/*
 * Copyright 2016 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.ospf.controller.impl;

import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler;
import org.jboss.netty.handler.timeout.ReadTimeoutException;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.controller.LsaWrapper;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfLinkTed;
import org.onosproject.ospf.controller.OspfLsa;
import org.onosproject.ospf.controller.OspfNbr;
import org.onosproject.ospf.controller.OspfNeighborState;
import org.onosproject.ospf.controller.OspfRouter;
import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
import org.onosproject.ospf.controller.area.OspfAreaImpl;
import org.onosproject.ospf.controller.area.OspfInterfaceImpl;
import org.onosproject.ospf.controller.lsdb.LsaWrapperImpl;
import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
import org.onosproject.ospf.controller.util.OspfEligibleRouter;
import org.onosproject.ospf.controller.util.OspfInterfaceType;
import org.onosproject.ospf.exceptions.OspfParseException;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.ospfpacket.OspfMessage;
import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader;
import org.onosproject.ospf.protocol.ospfpacket.subtype.LsRequestPacket;
import org.onosproject.ospf.protocol.ospfpacket.types.DdPacket;
import org.onosproject.ospf.protocol.ospfpacket.types.HelloPacket;
import org.onosproject.ospf.protocol.ospfpacket.types.LsAcknowledge;
import org.onosproject.ospf.protocol.ospfpacket.types.LsRequest;
import org.onosproject.ospf.protocol.ospfpacket.types.LsUpdate;
import org.onosproject.ospf.protocol.util.ChecksumCalculator;
import org.onosproject.ospf.protocol.util.OspfInterfaceState;
import org.onosproject.ospf.protocol.util.OspfPacketType;
import org.onosproject.ospf.protocol.util.OspfParameters;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Channel handler deals with the OSPF channel connection.
 * Also it dispatches messages to the appropriate handlers.
 */
public class OspfInterfaceChannelHandler extends IdleStateAwareChannelHandler {

    private static final Logger log =
            LoggerFactory.getLogger(OspfInterfaceChannelHandler.class);
    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    private OspfInterface ospfInterface;
    private OspfArea ospfArea;
    private boolean isClosed = false;
    private Controller controller;
    private Channel channel;
    private long delay = 0;
    private InternalHelloTimer helloTimerTask;
    private InternalWaitTimer waitTimerTask;
    private InternalDelayedAckTimer delayedAckTimerTask;
    private ScheduledExecutorService exServiceHello;
    private ScheduledExecutorService exServiceWait;
    private ScheduledExecutorService exServiceDelayedAck;
    private boolean isDelayedAckTimerScheduled = false;
    private int delayedAckTimerInterval = 2500;
    private TopologyForDeviceAndLink topologyForDeviceAndLink;

    public OspfInterfaceChannelHandler() {

    }

    /**
     * Creates an instance of OSPF channel handler.
     *
     * @param controller    controller instance
     * @param ospfArea      ospf area instance
     * @param ospfInterface ospf interface instance
     */
    public OspfInterfaceChannelHandler(Controller controller, OspfArea ospfArea, OspfInterface ospfInterface) {

        this.ospfArea = ospfArea;
        this.ospfInterface = ospfInterface;
        this.controller = controller;
        ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
        this.ospfInterface.setDr(Ip4Address.valueOf("0.0.0.0"));
        this.ospfInterface.setBdr(Ip4Address.valueOf("0.0.0.0"));
        this.topologyForDeviceAndLink = new TopologyForDeviceAndLinkImpl();
    }

    /**
     * Represents an interface is up and connected.
     *
     * @throws Exception might throws exception
     */
    public void interfaceUp() throws Exception {
        log.debug("OSPFInterfaceChannelHandler::interfaceUp...!!!");
        if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
            ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.POINT2POINT);
            log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} ",
                      ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());
        } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {
            //if router priority is 0, move the state to DROther
            if (ospfInterface.routerPriority() == 0) {
                ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
            } else {
                log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} RouterPriority {}",
                          ospfInterface.interfaceType(),
                          ((OspfInterfaceImpl) ospfInterface).state(), ospfInterface.routerPriority());
                ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.WAITING);
                //start wait timer - like inactivity timer with router deadInterval
                startWaitTimer();
            }

        }
        // Start hello timer with interval from config - convert seconds to milliseconds
        startHelloTimer(ospfInterface.helloIntervalTime());
        ospfArea.refreshArea(ospfInterface);
    }


    /**
     * Gets called when a BDR was detected before the wait timer expired.
     *
     * @param ch channel instance
     * @throws Exception might throws exception
     */
    public void backupSeen(Channel ch) throws Exception {
        log.debug("OSPFInterfaceChannelHandler::backupSeen ");
        if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
            electRouter(ch);
        }
    }

    /**
     * Gets called when no hello message received for particular period.
     *
     * @param ch channel instance
     * @throws Exception might throws exception
     */
    public void waitTimer(Channel ch) throws Exception {
        log.debug("OSPFInterfaceChannelHandler::waitTimer ");
        //section 9.4
        if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
            electRouter(ch);
        }
    }

    /**
     * Neighbor change event is triggered when the router priority gets changed.
     *
     * @throws Exception might throws exception
     */
    public void neighborChange() throws Exception {
        log.debug("OSPFInterfaceChannelHandler::neighborChange ");
        if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
                ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
                ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
            electRouter(channel);
        }
    }

    /**
     * Gets called when an interface is down.
     * All interface variables are reset, and interface timers disabled.
     * Also all neighbor connections associated with the interface are destroyed.
     */
    public void interfaceDown() {
        log.debug("OSPFInterfaceChannelHandler::interfaceDown ");
        stopHelloTimer();
        ospfInterface.listOfNeighbors().clear();
        ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DOWN);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent evt) throws Exception {
        log.info("OSPF channelConnected from {}", evt.getChannel().getRemoteAddress());
        channel = evt.getChannel();
        interfaceUp();
        startDelayedAckTimer();
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent evt) {
        interfaceDown();
        stopDelayedAckTimer();
        log.debug("OspfChannelHandler::channelDisconnected...!!!");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        log.info("[exceptionCaught]: " + e.toString());
        if (e.getCause() instanceof ReadTimeoutException) {
            // device timeout
            log.error("Disconnecting device {} due to read timeout", e.getChannel().getRemoteAddress());
            return;
        } else if (e.getCause() instanceof ClosedChannelException) {
            log.debug("Channel for OSPF {} already closed", e.getChannel().getRemoteAddress());
        } else if (e.getCause() instanceof IOException) {
            log.error("Disconnecting OSPF {} due to IO Error: {}", e.getChannel().getRemoteAddress(),
                      e.getCause().getMessage());
            if (log.isDebugEnabled()) {
                log.debug("StackTrace for previous Exception: {}", e.getCause());
            }
        } else if (e.getCause() instanceof OspfParseException) {
            OspfParseException errMsg = (OspfParseException) e.getCause();
            byte errorCode = errMsg.errorCode();
            byte errorSubCode = errMsg.errorSubCode();
            log.error("Error while parsing message from OSPF {}, ErrorCode {}",
                      e.getChannel().getRemoteAddress(), errorCode);
        } else if (e.getCause() instanceof RejectedExecutionException) {
            log.warn("Could not process message: queue full");
        } else {
            log.error("Error while processing message from OSPF {}, state {}",
                      e.getChannel().getRemoteAddress(), ((OspfInterfaceImpl) ospfInterface).state());
        }
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        log.debug("OspfChannelHandler::messageReceived...!!!");
        Object message = e.getMessage();
        if (message instanceof List) {
            List<OspfMessage> ospfMessageList = (List<OspfMessage>) message;
            log.debug("OspfChannelHandler::List of OspfMessages Size {}", ospfMessageList.size());
            if (ospfMessageList != null) {
                for (OspfMessage ospfMessage : ospfMessageList) {
                    processOspfMessage(ospfMessage, ctx);
                }
            } else {
                log.debug("OspfChannelHandler::OspfMessages Null List...!!");
            }
        }
        if (message instanceof OspfMessage) {
            OspfMessage ospfMessage = (OspfMessage) message;
            log.debug("OspfChannelHandler::OspfMessages received...!!");
            processOspfMessage(ospfMessage, ctx);
        }
    }

    /**
     * When an OSPF message received it is handed over to this method.
     * Based on the type of the OSPF message received it will be handed over
     * to corresponding message handler methods.
     *
     * @param ospfMessage received OSPF message
     * @param ctx         channel handler context instance.
     * @throws Exception might throws exception
     */
    public void processOspfMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processOspfMessage...!!!");

        if (!validateMessage(ospfMessage)) {
            return;
        }

        switch (ospfMessage.ospfMessageType().value()) {
            case OspfParameters.HELLO:
                processHelloMessage(ospfMessage, ctx);
                break;
            case OspfParameters.DD:
                processDdMessage(ospfMessage, ctx);
                break;
            case OspfParameters.LSREQUEST:
                processLsRequestMessage(ospfMessage, ctx);
                break;
            case OspfParameters.LSUPDATE:
                processLsUpdateMessage(ospfMessage, ctx);
                break;
            case OspfParameters.LSACK:
                processLsAckMessage(ospfMessage, ctx);
                break;
            default:
                log.debug("Unknown packet to process...!!!");
                break;
        }
    }

    /**
     * Validates the OSPF message received.
     *
     * @param ospfMessage OSPF message.
     * @return true if it is a valid else false.
     * @throws Exception might throws exception
     */
    private boolean validateMessage(OspfMessage ospfMessage) throws Exception {
        boolean isValid = true;
        OspfPacketHeader header = (OspfPacketHeader) ospfMessage;

        //added the check to eliminate self origin packets also two interfaces on same router.
        if (!header.sourceIp().equals(ospfInterface.ipAddress()) && !header.routerId().equals(
                ospfArea.routerId())) {
            //Verify the checksum
            ChecksumCalculator checksum = new ChecksumCalculator();
            if (!checksum.isValidOspfCheckSum(ospfMessage, OspfUtil.OSPFPACKET_CHECKSUM_POS1,
                                              OspfUtil.OSPFPACKET_CHECKSUM_POS2)) {
                log.debug("Checksum mismatch. Received packet type {} ", ospfMessage.ospfMessageType());
                return false;
            }
            if (((OspfPacketHeader) ospfMessage).ospfVersion() != OspfUtil.OSPF_VERSION_2) {
                log.debug("Received osfpMessage Version should match with Interface Version ");
                return false;
            }
            if (!((OspfPacketHeader) ospfMessage).areaId().equals(ospfArea.areaId())) {
                log.debug("Received ospf packets are from different area than our Area ID. " +
                                  "Received Area ID {}, Our AreaId {} ",
                          ((OspfPacketHeader) ospfMessage).areaId(), ospfArea.areaId());
                return false;
            }

            //According to RFC-2328 (8.2)
            /**
             * ABR should receive packets from backbone 0.0.0.0 as we are not acting as ABR
             * we are rejecting the packet.
             */
            if (((OspfPacketHeader) ospfMessage).areaId().equals(Ip4Address.valueOf("0.0.0.0"))) {
                log.debug("ABR should receive packets from backbone 0.0.0.0 as we are not acting as " +
                                  "ABR we are rejecting the ospf packet");
                return false;
            }
            if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value() &&
                    !OspfUtil.sameNetwork(((OspfPacketHeader) ospfMessage).sourceIp(),
                                          ospfInterface.ipAddress(), ospfInterface.ipNetworkMask())) {
                log.debug("Received packets from different subnets. Discarding...!!!");
                return false;
            }
        } else {
            isValid = false;
        }

        return isValid;
    }

    /**
     * Processes Hello message.
     *
     * @param ospfMessage OSPF message instance.
     * @param ctx         context instance.
     * @throws Exception might throws exception
     */
    void processHelloMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processHelloMessage...!!!");
        HelloPacket helloPacket = (HelloPacket) ospfMessage;

        // processing of hello packet as per RFC 2328 section 10.5
        log.debug("OspfChannelHandler::processHelloMessage::Interface Type {} OSPFInterfaceState {} ",
                  ospfInterface.interfaceType(), ((OspfInterfaceImpl) ospfInterface).state());

        if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
            if (!helloPacket.networkMask().equals(ospfInterface.ipNetworkMask())) {
                log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received does not " +
                                  "match the same network mask as the configure Interface");
                return;
            }
        }
        if (helloPacket.helloInterval() != ospfInterface.helloIntervalTime()) {
            log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
                              "hello interval as configured Interface");
            return;
        }
        if (helloPacket.routerDeadInterval() != ospfInterface.routerDeadIntervalTime()) {
            log.debug("OspfChannelHandler::processHelloMessage::Hello Packet Received have the same " +
                              "Router Dead interval as configured Interface");
            return;
        }

        if (ospfInterface.interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
            // to verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
            OspfNbr nbr;
            if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
                nbr = new OspfNbrImpl(ospfArea, ospfInterface, helloPacket.sourceIp(),
                                      helloPacket.routerId(), helloPacket.options(), this, topologyForDeviceAndLink);
                ospfInterface.addNeighbouringRouter(nbr);
            } else {
                nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
                nbr.setRouterPriority(helloPacket.routerPriority());
            }
            if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
                ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
            } else {
                ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
            }
        } else if (ospfInterface.interfaceType() == OspfInterfaceType.BROADCAST.value()) {

            if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.WAITING) {
                if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0"))) &&
                        (!helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))) {
                    stopWaitTimer();
                    ospfInterface.setDr(helloPacket.dr());
                    ospfInterface.setBdr(helloPacket.bdr());
                    if (helloPacket.dr().equals(ospfInterface.ipAddress())) {
                        ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
                        //refresh router Lsa
                        ospfArea.refreshArea(ospfInterface);
                    } else if (helloPacket.bdr().equals(ospfInterface.ipAddress())) {
                        ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
                        //refresh router Lsa
                        ospfArea.refreshArea(ospfInterface);
                    } else {
                        ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DROTHER);
                        ospfArea.refreshArea(ospfInterface);
                    }

                } else if (!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
                        !helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
                    ospfInterface.setDr(helloPacket.dr());
                    ospfInterface.setBdr(helloPacket.bdr());
                }
                Ip4Address sourceIp = helloPacket.sourceIp();
                OspfNbr nbr;
                if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
                    nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
                                          helloPacket.options(), this, topologyForDeviceAndLink);
                    nbr.setNeighborId(helloPacket.routerId());
                    nbr.setNeighborBdr(helloPacket.bdr());
                    nbr.setNeighborDr(helloPacket.dr());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                    ospfInterface.addNeighbouringRouter(nbr);
                } else {
                    nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                }
                if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
                    ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
                } else {
                    ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
                }

                if (helloPacket.dr().equals(sourceIp)) {
                    if (helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
                        // call backup seen
                        stopWaitTimer();
                        backupSeen(ctx.getChannel());
                    }
                }

                if (helloPacket.bdr().equals(sourceIp)) {
                    // call backup seen
                    stopWaitTimer();
                    backupSeen(ctx.getChannel());
                }
            } else {

                if ((!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
                        !helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0")))
                        && ospfInterface.routerPriority() == 0) {
                    ospfInterface.setDr(helloPacket.dr());
                    ospfInterface.setBdr(helloPacket.bdr());
                }
                //To verify if the neighbor which sent the hello is present in the OSPF Interface neighboring list .
                Ip4Address sourceIp = helloPacket.sourceIp();
                OspfNbr nbr;
                if (!ospfInterface.isNeighborInList(helloPacket.routerId().toString())) {
                    nbr = new OspfNbrImpl(ospfArea, ospfInterface, sourceIp, helloPacket.routerId(),
                                          helloPacket.options(), this, topologyForDeviceAndLink);
                    nbr.setNeighborId(helloPacket.routerId());
                    nbr.setNeighborBdr(helloPacket.bdr());
                    nbr.setNeighborDr(helloPacket.dr());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                    ospfInterface.addNeighbouringRouter(nbr);
                    ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
                } else {
                    log.debug("OspfChannelHandler::NeighborInList::helloPacket.bdr(): {}, " +
                                      "helloPacket.dr(): {}", helloPacket.bdr(), helloPacket.dr());
                    nbr = ospfInterface.neighbouringRouter(helloPacket.routerId().toString());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                    if (!helloPacket.containsNeighbour(ospfArea.routerId())) {
                        ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
                    } else {
                        ((OspfNbrImpl) nbr).twoWayReceived(helloPacket, ctx.getChannel());
                    }
                    if (nbr.routerPriority() != helloPacket.routerPriority()) {
                        nbr.setNeighborBdr(helloPacket.bdr());
                        nbr.setNeighborDr(helloPacket.dr());
                        neighborChange();
                    }


                    if (nbr.neighborIpAddr().equals(helloPacket.dr()) &&
                            !(nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
                        nbr.setNeighborBdr(helloPacket.bdr());
                        nbr.setNeighborDr(helloPacket.dr());
                        neighborChange();
                    }

                    if (!(nbr.neighborIpAddr().equals(helloPacket.dr())) &&
                            (nbr.neighborIpAddr().equals(nbr.neighborDr()))) {
                        nbr.setNeighborBdr(helloPacket.bdr());
                        nbr.setNeighborDr(helloPacket.dr());
                        neighborChange();
                    }

                    if (nbr.neighborIpAddr().equals(helloPacket.bdr()) &&
                            !(nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
                        nbr.setNeighborBdr(helloPacket.bdr());
                        nbr.setNeighborDr(helloPacket.dr());
                        neighborChange();
                    }

                    if (!(nbr.neighborIpAddr().equals(helloPacket.bdr())) &&
                            (nbr.neighborIpAddr().equals(nbr.neighborBdr()))) {
                        nbr.setNeighborBdr(helloPacket.bdr());
                        nbr.setNeighborDr(helloPacket.dr());
                        neighborChange();
                    }

                    nbr.setNeighborBdr(helloPacket.bdr());
                    nbr.setNeighborDr(helloPacket.dr());
                }

            }
        }
    }

    /**
     * process the DD message which received.
     *
     * @param ospfMessage OSPF message instance.
     * @param ctx         channel handler context instance
     * @throws Exception might throws exception
     */
    void processDdMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processDdMessage...!!!");

        DdPacket ddPacket = (DdPacket) ospfMessage;
        log.debug("Got DD packet from {}", ddPacket.sourceIp());
        //check it is present in listOfNeighbors
        Ip4Address neighbourId = ddPacket.routerId();
        OspfNbr nbr = ospfInterface.neighbouringRouter(neighbourId.toString());

        if (nbr != null) {
            log.debug("OspfChannelHandler::processDdMessage:: OSPFNeighborState {}", nbr.getState());
            // set options for the NBR
            nbr.setIsOpaqueCapable(ddPacket.isOpaqueCapable());
            if (ddPacket.imtu() > ospfInterface.mtu()) {
                log.debug("the MTU size is greater than the interface MTU");
                return;
            }
            if (nbr.getState() == OspfNeighborState.DOWN) {
                return;
            }
            if (nbr.getState() == OspfNeighborState.ATTEMPT) {
                return;
            }
            if (nbr.getState() == OspfNeighborState.TWOWAY) {
                nbr.adjOk(channel);
                return;
            }
            //if init is the state call twoWayReceived
            if (nbr.getState() == OspfNeighborState.INIT) {
                ((OspfNbrImpl) nbr).twoWayReceived(ddPacket, ctx.getChannel());
            } else if (nbr.getState() == OspfNeighborState.EXSTART) {
                //get I,M,MS Bits
                int initialize = ddPacket.isInitialize();
                int more = ddPacket.isMore();
                int masterOrSlave = ddPacket.isMaster();
                int options = ddPacket.options();
                nbr.setOptions(options);

                if (initialize == OspfUtil.INITIALIZE_SET && more == OspfUtil.MORE_SET &&
                        masterOrSlave == OspfUtil.IS_MASTER) {
                    if (ddPacket.getLsaHeaderList().isEmpty()) {
                        if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) >
                                OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
                            nbr.setIsMaster(OspfUtil.IS_MASTER);
                            ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
                            nbr.setDdSeqNum(ddPacket.sequenceNo());
                            nbr.setOptions(ddPacket.options());
                            ((OspfNbrImpl) nbr).negotiationDone(ddPacket, true, ddPacket.getLsaHeaderList(),
                                                                ctx.getChannel());
                        }
                    }
                }
                if (initialize == OspfUtil.INITIALIZE_NOTSET && masterOrSlave == OspfUtil.NOT_MASTER) {
                    if (nbr.ddSeqNum() == ddPacket.sequenceNo()) {
                        if (OspfUtil.ipAddressToLong(ddPacket.routerId().toString()) <
                                OspfUtil.ipAddressToLong(ospfArea.routerId().toString())) {
                            ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
                            nbr.setOptions(ddPacket.options());
                            nbr.setDdSeqNum(nbr.ddSeqNum() + 1);
                            ((OspfNbrImpl) nbr).negotiationDone(ddPacket, false, ddPacket.getLsaHeaderList(),
                                                                ctx.getChannel());
                        }
                    }
                }

            } else if (nbr.getState() == OspfNeighborState.EXCHANGE) {
                //get I,M,MS Bits
                log.debug("Neighbor state:: EXCHANGE");
                boolean isDuplicateDDPacket = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
                int initialize = ddPacket.isInitialize();
                int more = ddPacket.isMore();
                int masterOrSlave = ddPacket.isMaster();
                int options = ddPacket.options();

                if (!isDuplicateDDPacket) {
                    //if dd packet is not duplicate  then continue
                    if (nbr.isMaster() != masterOrSlave) {
                        DdPacket newResPacket =
                                (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Master/Slave Inconsistency");
                        newResPacket.setDestinationIp(ddPacket.sourceIp());
                        log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                        ctx.getChannel().write(newResPacket);
                    } else if (initialize == 1) {
                        DdPacket newResPacket =
                                (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
                        newResPacket.setDestinationIp(ddPacket.sourceIp());
                        log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                        ctx.getChannel().write(newResPacket);
                    } else {

                        if (masterOrSlave == OspfUtil.NOT_MASTER) {
                            if (ddPacket.sequenceNo() == nbr.ddSeqNum()) {
                                //Process the DD Packet
                                ((OspfNbrImpl) nbr).processDdPacket(false, ddPacket, ctx.getChannel());
                                log.debug("Received DD Packet");
                            } else {
                                DdPacket newResPacket =
                                        (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("Sequence Number Mismatch");
                                newResPacket.setDestinationIp(ddPacket.sourceIp());
                                log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                                ctx.getChannel().write(newResPacket);
                            }
                        } else {
                            //we are the slave
                            if (ddPacket.sequenceNo() == (nbr.ddSeqNum() + 1)) {
                                ((OspfNbrImpl) nbr).setLastDdPacket(ddPacket);
                                ((OspfNbrImpl) nbr).processDdPacket(true, ddPacket, ctx.getChannel());
                                log.debug("Process DD Packet");
                            } else {
                                DdPacket newResPacket =
                                        (DdPacket) ((OspfNbrImpl) nbr).seqNumMismatch("options inconsistency");
                                newResPacket.setDestinationIp(ddPacket.sourceIp());
                                log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                                ctx.getChannel().write(newResPacket);
                            }
                        }
                    }
                } else {
                    if (masterOrSlave == OspfUtil.NOT_MASTER) {
                        return;
                    } else {
                        DdPacket newResPacket = ((OspfNbrImpl) nbr).lastSentDdPacket();
                        log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                        ctx.getChannel().write(newResPacket);
                    }
                }
            } else if (nbr.getState() == OspfNeighborState.LOADING || nbr.getState() == OspfNeighborState.FULL) {
                //In case if we are slave then we have to send the last received DD Packet
                int options = ddPacket.options();
                if (nbr.options() != options) {
                    OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
                    newResPacket.setDestinationIp(ddPacket.sourceIp());
                    ctx.getChannel().write(newResPacket);
                } else if (ddPacket.isInitialize() == OspfUtil.INITIALIZE_SET) {
                    OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
                    newResPacket.setDestinationIp(ddPacket.sourceIp());
                    ctx.getChannel().write(newResPacket);
                }
                boolean isDuplicate = compareDdPackets(ddPacket, ((OspfNbrImpl) nbr).lastDdPacket());
                //we are master
                if (nbr.isMaster() != OspfUtil.IS_MASTER) {
                    // check if the packet is duplicate, duplicates should be discarded by the master
                    if (isDuplicate) {
                        log.debug("received a duplicate DD packet");
                    }
                } else {
                    //The slave must respond to duplicates by repeating the last Database Description packet
                    //that it had sent.
                    if (isDuplicate) {
                        ddPacket.setDestinationIp(ddPacket.sourceIp());
                        ctx.getChannel().write(((OspfNbrImpl) nbr).lastSentDdPacket());
                        log.debug("Sending back the duplicate packet ");
                    }
                }
            }
        }
    }

    /**
     * Process the Ls Request message.
     *
     * @param ospfMessage OSPF message instance.
     * @param ctx         channel handler context instance.
     * @throws Exception might throws exception
     */
    void processLsRequestMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processLsRequestMessage...!!!");
        LsRequest lsrPacket = (LsRequest) ospfMessage;
        OspfNbr nbr = ospfInterface.neighbouringRouter(lsrPacket.routerId().toString());

        if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING ||
                nbr.getState() == OspfNeighborState.FULL) {

            LsRequest reqMsg = (LsRequest) ospfMessage;
            if (reqMsg.getLinkStateRequests().isEmpty()) {
                log.debug("Received Link State Request Vector is Empty ");
                return;
            } else {
                //Send the LsUpdate back
                ListIterator<LsRequestPacket> listItr = reqMsg.getLinkStateRequests().listIterator();
                while (listItr.hasNext()) {
                    LsUpdate lsupdate = new LsUpdate();
                    lsupdate.setOspfVer(OspfUtil.OSPF_VERSION);
                    lsupdate.setOspftype(OspfPacketType.LSUPDATE.value());
                    lsupdate.setRouterId(ospfArea.routerId());
                    lsupdate.setAreaId(ospfArea.areaId());
                    lsupdate.setAuthType(OspfUtil.NOT_ASSIGNED);
                    lsupdate.setAuthentication(OspfUtil.NOT_ASSIGNED);
                    lsupdate.setOspfPacLength(OspfUtil.NOT_ASSIGNED); // to calculate packet length
                    lsupdate.setChecksum(OspfUtil.NOT_ASSIGNED);

                    //limit to mtu
                    int currentLength = OspfUtil.OSPF_HEADER_LENGTH + OspfUtil.FOUR_BYTES;
                    int maxSize = ospfInterface.mtu() -
                            OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
                    int noLsa = 0;
                    while (listItr.hasNext()) {
                        LsRequestPacket lsRequest = (LsRequestPacket) listItr.next();
                        // to verify length of the LSA
                        LsaWrapper wrapper = ospfArea.getLsa(lsRequest.lsType(), lsRequest.linkStateId(),
                                                             lsRequest.ownRouterId());
                        OspfLsa ospflsa = wrapper.ospfLsa();
                        if ((currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen()) >= maxSize) {
                            listItr.previous();
                            break;
                        }
                        if (ospflsa != null) {
                            lsupdate.addLsa(ospflsa);
                            noLsa++;

                            currentLength = currentLength + ((LsaWrapperImpl) wrapper).lsaHeader().lsPacketLen();
                        } else {
                            nbr.badLSReq(channel);
                        }
                    }
                    lsupdate.setNumberOfLsa(noLsa);
                    //set the destination
                    if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
                            ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR ||
                            ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
                        lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
                    } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
                        lsupdate.setDestinationIp(OspfUtil.ALL_DROUTERS);
                    }
                    ctx.getChannel().write(lsupdate);
                }
            }
        }
    }

    /**
     * Process the ls update message.
     *
     * @param ospfMessage OSPF message instance.
     * @param ctx         channel handler context instance.
     * @throws Exception might throws exception
     */
    void processLsUpdateMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processLsUpdateMessage");
        LsUpdate lsUpdate = (LsUpdate) ospfMessage;
        String neighbourId = lsUpdate.routerId().toString();
        //LSUpdate packet has been associated with a particular neighbor.
        //Neighbor should not be in lesser state than Exchange.
        if (ospfInterface.isNeighborInList(neighbourId)) {
            OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(neighbourId);
            if (nbr.getState() == OspfNeighborState.EXCHANGE ||
                    nbr.getState() == OspfNeighborState.LOADING) {
                nbr.processLsUpdate(lsUpdate, ctx.getChannel());
            } else if (nbr.getState() == OspfNeighborState.FULL) {
                if (lsUpdate.noLsa() != 0) {
                    List<OspfLsa> list = lsUpdate.getLsaList();
                    Iterator itr = list.iterator();
                    while (itr.hasNext()) {
                        LsaHeader lsa = (LsaHeader) itr.next();
                        nbr.processReceivedLsa(lsa, true, ctx.getChannel(), lsUpdate.sourceIp());
                    }
                } else {
                    return;
                }
            }
        }
    }

    /**
     * Process the ls acknowledge message.
     *
     * @param ospfMessage OSPF message instance.
     * @param ctx         channel handler context instance.
     * @throws Exception might throws exception
     */
    void processLsAckMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
        log.debug("OspfChannelHandler::processLsAckMessage");
        LsAcknowledge lsAckPacket = (LsAcknowledge) ospfMessage;
        //check it is present in listOfNeighbors
        OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(lsAckPacket.routerId().toString());
        if (nbr != null) {
            if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
                // discard the packet.
                return;
            } else {
                // process ls acknowledgements
                Iterator itr = lsAckPacket.getLinkStateHeaders().iterator();
                while (itr.hasNext()) {
                    LsaHeader lsRequest = (LsaHeader) itr.next();

                    OspfLsa ospfLsa =
                            (OspfLsa) nbr.getPendingReTxList().get(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
                    if (lsRequest != null && ospfLsa != null) {
                        String isSame = ((OspfLsdbImpl) ospfArea.database()).isNewerOrSameLsa(
                                lsRequest, (LsaHeader) ospfLsa);
                        if (isSame.equals("same")) {
                            nbr.getPendingReTxList().remove(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
                        }
                    }
                }
            }
        }
    }

    /**
     * Compares two Dd Packets to check whether its duplicate or not.
     *
     * @param receivedDPacket received DD packet from network.
     * @param lastDdPacket    Last DdPacket which we sent.
     * @return true if it is a duplicate packet else false.
     */
    public boolean compareDdPackets(DdPacket receivedDPacket, DdPacket lastDdPacket) {
        if (receivedDPacket.isInitialize() == lastDdPacket.isInitialize()) {
            if (receivedDPacket.isMaster() == lastDdPacket.isMaster()) {
                if (receivedDPacket.isMore() == lastDdPacket.isMore()) {
                    if (receivedDPacket.options() == lastDdPacket.options()) {
                        if (receivedDPacket.sequenceNo() == lastDdPacket.sequenceNo()) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

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

    /**
     * Starts the hello timer which sends hello packet every configured seconds.
     *
     * @param period the interval to run task
     */
    private void startHelloTimer(long period) {
        log.debug("OSPFInterfaceChannelHandler::startHelloTimer");
        exServiceHello = Executors.newSingleThreadScheduledExecutor();
        helloTimerTask = new InternalHelloTimer();
        final ScheduledFuture<?> helloHandle =
                exServiceHello.scheduleAtFixedRate(helloTimerTask, delay, period, TimeUnit.SECONDS);
    }

    /**
     * Stops the hello timer.
     */
    private void stopHelloTimer() {
        log.debug("OSPFInterfaceChannelHandler::stopHelloTimer ");
        exServiceHello.shutdown();
    }

    /**
     * Starts the wait timer.
     */
    private void startWaitTimer() {
        log.debug("OSPFNbr::startWaitTimer");
        exServiceWait = Executors.newSingleThreadScheduledExecutor();
        waitTimerTask = new InternalWaitTimer();
        final ScheduledFuture<?> waitTimerHandle =
                exServiceWait.schedule(waitTimerTask, ospfInterface.routerDeadIntervalTime(),
                                       TimeUnit.SECONDS);
    }

    /**
     * Stops the wait timer.
     */
    private void stopWaitTimer() {
        log.debug("OSPFNbr::stopWaitTimer ");
        exServiceWait.shutdown();
    }

    /**
     * Starts the timer which waits for configured seconds and sends Delayed Ack Packet.
     */
    private void startDelayedAckTimer() {
        if (!isDelayedAckTimerScheduled) {
            log.debug("Started DelayedAckTimer...!!!");
            exServiceDelayedAck = Executors.newSingleThreadScheduledExecutor();
            delayedAckTimerTask = new InternalDelayedAckTimer();
            final ScheduledFuture<?> delayAckHandle =
                    exServiceDelayedAck.scheduleAtFixedRate(delayedAckTimerTask, delayedAckTimerInterval,
                                                            delayedAckTimerInterval, TimeUnit.MILLISECONDS);
            isDelayedAckTimerScheduled = true;
        }
    }

    /**
     * Stops the delayed acknowledge timer.
     */
    private void stopDelayedAckTimer() {
        if (isDelayedAckTimerScheduled) {
            log.debug("Stopped DelayedAckTimer...!!!");
            isDelayedAckTimerScheduled = false;
            exServiceDelayedAck.shutdown();
        }
    }

    /**
     * Performs DR election.
     *
     * @param ch Netty Channel instance.
     * @throws Exception might throws exception
     */
    public void electRouter(Channel ch) throws Exception {

        Ip4Address currentDr = ospfInterface.dr();
        Ip4Address currentBdr = ospfInterface.bdr();
        OspfInterfaceState oldState = ((OspfInterfaceImpl) ospfInterface).state();
        OspfInterfaceState newState;

        log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
                  currentDr, currentBdr);
        List<OspfEligibleRouter> eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());

        log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
        OspfEligibleRouter electedBdr = electBdr(eligibleRouters);
        OspfEligibleRouter electedDr = electDr(eligibleRouters, electedBdr);

        ospfInterface.setBdr(electedBdr.getIpAddress());
        ospfInterface.setDr(electedDr.getIpAddress());

        if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
                !electedBdr.getIpAddress().equals(currentBdr)) {
            ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
        }

        if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
                !electedDr.getIpAddress().equals(currentDr)) {
            ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
        }

        if (((OspfInterfaceImpl) ospfInterface).state() != oldState &&
                !(((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER &&
                        oldState.value() < OspfInterfaceState.DROTHER.value())) {
            log.debug("Recalculating as the State is changed ");
            log.debug("OSPFInterfaceChannelHandler::electRouter -> currentDr: {}, currentBdr: {}",
                      currentDr, currentBdr);
            eligibleRouters = calculateListOfEligibleRouters(new OspfEligibleRouter());

            log.debug("OSPFInterfaceChannelHandler::electRouter -> eligibleRouters: {}", eligibleRouters);
            electedBdr = electBdr(eligibleRouters);
            electedDr = electDr(eligibleRouters, electedBdr);

            ospfInterface.setBdr(electedBdr.getIpAddress());
            ospfInterface.setDr(electedDr.getIpAddress());
        }

        if (electedBdr.getIpAddress().equals(ospfInterface.ipAddress()) &&
                !electedBdr.getIpAddress().equals(currentBdr)) {
            ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.BDR);
            ospfArea.refreshArea(ospfInterface);
        }

        if (electedDr.getIpAddress().equals(ospfInterface.ipAddress()) &&
                !electedDr.getIpAddress().equals(currentDr)) {
            ((OspfInterfaceImpl) ospfInterface).setState(OspfInterfaceState.DR);
            //Refresh Router Lsa & Network Lsa
            ospfArea.refreshArea(ospfInterface);
        }

        if (currentDr != electedDr.getIpAddress() || currentBdr != electedBdr.getIpAddress()) {
            Set<String> negibhorIdList;
            negibhorIdList = ospfInterface.listOfNeighbors().keySet();
            for (String routerid : negibhorIdList) {
                OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerid);
                if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue()) {
                    nbr.adjOk(ch);
                }
            }
        }

        log.debug("OSPFInterfaceChannelHandler::electRouter -> ElectedDR: {}, ElectedBDR: {}",
                  electedDr.getIpAddress(), electedBdr.getIpAddress());
    }


    /**
     * BDR Election process. Find the list of eligible router to participate in the process.
     *
     * @param electedDr router elected as DR.
     * @return list of eligible routers
     */
    public List<OspfEligibleRouter> calculateListOfEligibleRouters(OspfEligibleRouter electedDr) {
        log.debug("OSPFNbr::calculateListOfEligibleRouters ");
        Set<String> neighborIdList;
        List<OspfEligibleRouter> eligibleRouters = new ArrayList<>();

        neighborIdList = ospfInterface.listOfNeighbors().keySet();
        for (String routerId : neighborIdList) {
            OspfNbrImpl nbr = (OspfNbrImpl) ospfInterface.neighbouringRouter(routerId);
            if (nbr.getState().getValue() >= OspfNeighborState.TWOWAY.getValue() &&
                    nbr.routerPriority() > 0) {
                OspfEligibleRouter router = new OspfEligibleRouter();
                router.setIpAddress(nbr.neighborIpAddr());
                router.setRouterId(nbr.neighborId());
                router.setRouterPriority(nbr.routerPriority());
                if (nbr.neighborDr().equals(nbr.neighborIpAddr()) ||
                        electedDr.getIpAddress().equals(nbr.neighborIpAddr())) {
                    router.setIsDr(true);
                } else if (nbr.neighborBdr().equals(nbr.neighborIpAddr())) {
                    router.setIsBdr(true);
                }
                eligibleRouters.add(router);
            }
        }
        // interface does not have states like two and all
        if (ospfInterface.routerPriority() > 0) {
            OspfEligibleRouter router = new OspfEligibleRouter();
            router.setIpAddress(ospfInterface.ipAddress());
            router.setRouterId(ospfArea.routerId());
            router.setRouterPriority(ospfInterface.routerPriority());
            if (ospfInterface.dr().equals(ospfInterface.ipAddress()) ||
                    electedDr.getIpAddress().equals(ospfInterface.ipAddress())) {
                router.setIsDr(true);
            } else if (ospfInterface.bdr().equals(ospfInterface.ipAddress()) &&
                    !ospfInterface.dr().equals(ospfInterface.ipAddress())) {
                router.setIsBdr(true);
            }

            eligibleRouters.add(router);
        }

        return eligibleRouters;
    }

    /**
     * Based on router priority assigns BDR.
     *
     * @param eligibleRouters list of routers to participate in bdr election.
     * @return OSPF Eligible router instance.
     */
    public OspfEligibleRouter electBdr(List<OspfEligibleRouter> eligibleRouters) {
        log.debug("OSPFInterfaceChannelHandler::electBdr -> eligibleRouters: {}", eligibleRouters);
        List<OspfEligibleRouter> declaredAsBdr = new ArrayList<>();
        List<OspfEligibleRouter> notDrAndBdr = new ArrayList<>();
        for (OspfEligibleRouter router : eligibleRouters) {
            if (router.isBdr()) {
                declaredAsBdr.add(router);
            }
            if (!router.isBdr() && !router.isDr()) {
                notDrAndBdr.add(router);
            }
        }

        OspfEligibleRouter electedBdr = new OspfEligibleRouter();
        if (!declaredAsBdr.isEmpty()) {
            if (declaredAsBdr.size() == 1) {
                electedBdr = declaredAsBdr.get(0);
            } else if (declaredAsBdr.size() > 1) {
                electedBdr = selectRouterBasedOnPriority(declaredAsBdr);
            }
        } else {
            if (notDrAndBdr.size() == 1) {
                electedBdr = notDrAndBdr.get(0);
            } else if (notDrAndBdr.size() > 1) {
                electedBdr = selectRouterBasedOnPriority(notDrAndBdr);
            }
        }

        electedBdr.setIsBdr(true);
        electedBdr.setIsDr(false);

        return electedBdr;
    }

    /**
     * DR Election process.
     *
     * @param eligibleRouters list of eligible routers.
     * @param electedBdr      Elected Bdr, OSPF eligible router instance.
     * @return OSPF eligible router instance.
     */
    public OspfEligibleRouter electDr(List<OspfEligibleRouter> eligibleRouters,
                                      OspfEligibleRouter electedBdr) {

        List<OspfEligibleRouter> declaredAsDr = new ArrayList<>();
        for (OspfEligibleRouter router : eligibleRouters) {
            if (router.isDr()) {
                declaredAsDr.add(router);
            }
        }

        OspfEligibleRouter electedDr = new OspfEligibleRouter();
        if (!declaredAsDr.isEmpty()) {
            if (declaredAsDr.size() == 1) {
                electedDr = declaredAsDr.get(0);
            } else if (eligibleRouters.size() > 1) {
                electedDr = selectRouterBasedOnPriority(declaredAsDr);
            }
        } else {
            electedDr = electedBdr;
            electedDr.setIsDr(true);
            electedDr.setIsBdr(false);
        }

        return electedDr;
    }

    /**
     * DR election process.
     *
     * @param routersList list of eligible routers.
     * @return OSPF eligible router instance.
     */
    public OspfEligibleRouter selectRouterBasedOnPriority(List<OspfEligibleRouter> routersList) {

        OspfEligibleRouter initialRouter = routersList.get(0);

        for (int i = 1; i < routersList.size(); i++) {
            OspfEligibleRouter router = routersList.get(i);
            if (router.getRouterPriority() > initialRouter.getRouterPriority()) {
                initialRouter = router;
            } else if (router.getRouterPriority() == initialRouter.getRouterPriority()) {
                try {
                    //if (router.getIpAddress().toInt() > initialRouter.getIpAddress().toInt()) {
                    if (OspfUtil.ipAddressToLong(router.getIpAddress().toString()) >
                            OspfUtil.ipAddressToLong(initialRouter.getIpAddress().toString())) {
                        initialRouter = router;
                    }
                } catch (Exception e) {
                    log.debug("OSPFInterfaceChannelHandler::selectRouterBasedOnPriority ->" +
                                      " eligibleRouters: {}", initialRouter);
                }
            }
        }

        return initialRouter;
    }

    /**
     * Adds device information.
     *
     * @param ospfRouter OSPF router instance
     */
    public void addDeviceInformation(OspfRouter ospfRouter) {
        controller.addDeviceDetails(ospfRouter);
    }

    /**
     * removes device information.
     *
     * @param ospfRouter OSPF neighbor instance
     */
    public void removeDeviceInformation(OspfRouter ospfRouter) {
        controller.removeDeviceDetails(ospfRouter);
    }

    /**
     * Adds link information.
     *
     * @param ospfRouter  OSPF router instance
     * @param ospfLinkTed list link ted instances
     */
    public void addLinkInformation(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
        controller.addLinkDetails(ospfRouter, ospfLinkTed);
    }

    /**
     * Removes link information.
     *
     * @param ospfNbr OSPF neighbor instance
     */
    public void removeLinkInformation(OspfNbr ospfNbr) {
        controller.removeLinkDetails(buildOspfRouterDetails(ospfNbr));
    }

    /**
     * Builds router details.
     *
     * @param ospfNbr OSPF neighbor instance
     * @return OSPF router instance
     */
    private OspfRouter buildOspfRouterDetails(OspfNbr ospfNbr) {
        OspfRouter ospfRouter = new OspfRouterImpl();
        ospfRouter.setRouterIp(ospfNbr.neighborId());
        ospfRouter.setInterfaceId(ospfInterface.ipAddress());
        ospfRouter.setAreaIdOfInterface(ospfArea.areaId());

        ospfRouter.setDeviceTed(new OspfDeviceTedImpl());

        return ospfRouter;
    }

    /**
     * Represents a Hello task which sent a hello message every configured time interval.
     */
    private class InternalHelloTimer implements Runnable {

        /**
         * Creates an instance of Hello Timer.
         */
        InternalHelloTimer() {
        }

        @Override
        public void run() {
            if (!isClosed && channel != null && channel.isOpen() && channel.isConnected()) {

                HelloPacket hellopacket = new HelloPacket();
                //Headers
                hellopacket.setOspfVer(OspfUtil.OSPF_VERSION);
                hellopacket.setOspftype(OspfPacketType.HELLO.value());
                hellopacket.setOspfPacLength(0); //will be modified while encoding
                hellopacket.setRouterId(ospfArea.routerId());
                hellopacket.setAreaId(ospfArea.areaId());
                hellopacket.setChecksum(0); //will be modified while encoding
                hellopacket.setAuthType(Integer.parseInt(ospfInterface.authType()));
                hellopacket.setAuthentication(Integer.parseInt(ospfInterface.authKey()));
                //Body
                hellopacket.setNetworkMask(ospfInterface.ipNetworkMask());
                hellopacket.setOptions(ospfArea.options());
                hellopacket.setHelloInterval(ospfInterface.helloIntervalTime());
                hellopacket.setRouterPriority(ospfInterface.routerPriority());
                hellopacket.setRouterDeadInterval(ospfInterface.routerDeadIntervalTime());
                hellopacket.setDr(ospfInterface.dr());
                hellopacket.setBdr(ospfInterface.bdr());

                HashMap<String, OspfNbr> listOfNeighbors = ospfInterface.listOfNeighbors();
                Set<String> keys = listOfNeighbors.keySet();
                Iterator itr = keys.iterator();
                while (itr.hasNext()) {
                    String nbrKey = (String) itr.next();
                    OspfNbrImpl nbr = (OspfNbrImpl) listOfNeighbors.get(nbrKey);
                    if (nbr.getState() != OspfNeighborState.DOWN) {
                        hellopacket.addNeighbor(Ip4Address.valueOf(nbrKey));
                    }
                }
                // build a hello Packet
                if (channel == null || !channel.isOpen() || !channel.isConnected()) {
                    log.debug("Hello Packet not sent !!.. Channel Issue...");
                    return;
                }

                hellopacket.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
                ChannelFuture future = channel.write(hellopacket);
                if (future.isSuccess()) {
                    log.debug("Hello Packet successfully sent !!");
                } else {
                    future.awaitUninterruptibly();
                }

            }
        }
    }

    /**
     * Represents a Wait Timer task which waits the interface state to become WAITING.
     * It initiates DR election process.
     */
    private class InternalWaitTimer implements Runnable {
        Channel ch;

        /**
         * Creates an instance of Wait Timer.
         */
        InternalWaitTimer() {
            this.ch = channel;
        }

        @Override
        public void run() {
            log.debug("Wait timer expires...");
            if (ch != null && ch.isConnected()) {
                try {
                    waitTimer(ch);
                } catch (Exception e) {
                    log.debug("Exception at wait timer ...!!!");
                }

            }
        }
    }

    /**
     * Represents a task which sent a LS Acknowledge from the link state headers list.
     */
    private class InternalDelayedAckTimer implements Runnable {
        Channel ch;

        /**
         * Creates an instance of Delayed acknowledge timer.
         */
        InternalDelayedAckTimer() {
            this.ch = channel;
        }

        @Override
        public void run() {
            if (!((OspfInterfaceImpl) ospfInterface).linkStateHeaders().isEmpty()) {
                isDelayedAckTimerScheduled = true;
                if (ch != null && ch.isConnected()) {

                    List<LsaHeader> listOfLsaHeadersAcknowledged = new ArrayList<>();
                    List<LsaHeader> listOfLsaHeaders = ((OspfInterfaceImpl) ospfInterface).linkStateHeaders();
                    log.debug("Delayed Ack, Number of Lsa's to Ack {}", listOfLsaHeaders.size());
                    Iterator itr = listOfLsaHeaders.iterator();
                    while (itr.hasNext()) {
                        LsAcknowledge ackContent = new LsAcknowledge();
                        //Setting OSPF Header
                        ackContent.setOspfVer(OspfUtil.OSPF_VERSION);
                        ackContent.setOspftype(OspfPacketType.LSAACK.value());
                        ackContent.setRouterId(ospfArea.routerId());
                        ackContent.setAreaId(ospfArea.areaId());
                        ackContent.setAuthType(OspfUtil.NOT_ASSIGNED);
                        ackContent.setAuthentication(OspfUtil.NOT_ASSIGNED);
                        ackContent.setOspfPacLength(OspfUtil.NOT_ASSIGNED);
                        ackContent.setChecksum(OspfUtil.NOT_ASSIGNED);
                        //limit to mtu
                        int currentLength = OspfUtil.OSPF_HEADER_LENGTH;
                        int maxSize = ospfInterface.mtu() -
                                OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
                        while (itr.hasNext()) {
                            if ((currentLength + OspfUtil.LSA_HEADER_LENGTH) >= maxSize) {
                                break;
                            }
                            LsaHeader lsaHeader = (LsaHeader) itr.next();
                            ackContent.addLinkStateHeader(lsaHeader);
                            currentLength = currentLength + OspfUtil.LSA_HEADER_LENGTH;
                            listOfLsaHeadersAcknowledged.add(lsaHeader);
                            log.debug("Delayed Ack, Added Lsa's to Ack {}", lsaHeader);
                        }

                        log.debug("Delayed Ack, Number of Lsa's in LsAck packet {}",
                                  ackContent.getLinkStateHeaders().size());

                        //set the destination
                        if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DR ||
                                ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.BDR
                                || ((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.POINT2POINT) {
                            ackContent.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
                        } else if (((OspfInterfaceImpl) ospfInterface).state() == OspfInterfaceState.DROTHER) {
                            ackContent.setDestinationIp(OspfUtil.ALL_DROUTERS);
                        }
                        ch.write(ackContent);
                        for (LsaHeader lsa : listOfLsaHeadersAcknowledged) {
                            ((OspfInterfaceImpl) ospfInterface).linkStateHeaders().remove(lsa);
                            ospfInterface.removeLsaFromNeighborMap(((OspfAreaImpl) ospfArea).getLsaKey(lsa));
                        }
                    }
                }
            }
        }
    }
}