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

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
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.OspfMessage;
import org.onosproject.ospf.controller.OspfNbr;
import org.onosproject.ospf.controller.OspfNeighborState;
import org.onosproject.ospf.controller.OspfPacketType;
import org.onosproject.ospf.controller.OspfRouter;
import org.onosproject.ospf.controller.TopologyForDeviceAndLink;
import org.onosproject.ospf.controller.impl.Controller;
import org.onosproject.ospf.controller.impl.OspfNbrImpl;
import org.onosproject.ospf.controller.impl.TopologyForDeviceAndLinkImpl;
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.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader;
import org.onosproject.ospf.protocol.ospfpacket.OspfMessageWriter;
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.OspfParameters;
import org.onosproject.ospf.protocol.util.OspfUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Representation of an OSPF interface.
 */
public class OspfInterfaceImpl implements OspfInterface {
    private static final Logger log = LoggerFactory.getLogger(OspfInterfaceImpl.class);
    private int interfaceIndex;
    private Ip4Address ipAddress;
    private Ip4Address ipNetworkMask;
    private Channel channel = null;
    private int helloIntervalTime;
    private int routerDeadIntervalTime;
    private int routerPriority;
    private int interfaceType;
    private int mtu;
    private int reTransmitInterval;
    private Ip4Address dr;
    private Ip4Address bdr;
    private OspfInterfaceState state;
    private List<LsaHeader> linkStateHeaders = new ArrayList<>();
    private Map<String, OspfNbr> listOfNeighbors = new ConcurrentHashMap<>();
    private Map<String, LsaHeader> listOfNeighborMap = new ConcurrentHashMap<>();
    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 int interfaceTypeOldValue = 0;
    private TopologyForDeviceAndLink topologyForDeviceAndLink = new TopologyForDeviceAndLinkImpl();
    private OspfArea ospfArea;
    private Controller controller;


    /**
     * Gets the interface state.
     *
     * @return interfaceState state of the interface
     */
    public OspfInterfaceState state() {
        return state;
    }

    /**
     * Sets the interface state.
     *
     * @param ospfInterfaceState interface state enum instance
     */
    public void setState(OspfInterfaceState ospfInterfaceState) {
        this.state = ospfInterfaceState;
    }

    /**
     * Sets the netty channel.
     *
     * @param channel channel
     */
    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    /**
     * Returns OSPF area instance.
     *
     * @return OSPF area instance
     */
    public OspfArea ospfArea() {
        return ospfArea;
    }

    /**
     * Sets OSPF controller instance.
     *
     * @param controller OSPF controller instance
     */
    public void setController(Controller controller) {
        this.controller = controller;
    }

    /**
     * Sets OSPF area instance.
     *
     * @param ospfArea OSPF area instance
     */
    public void setOspfArea(OspfArea ospfArea) {
        this.ospfArea = ospfArea;
    }

    /**
     * Gets interface state.
     *
     * @return interface state
     */
    public String interfaceState() {
        return state.interfaceState();
    }

    /**
     * Gets link state headers.
     *
     * @return get the list of lsa headers
     */
    public List<LsaHeader> linkStateHeaders() {
        Set<String> key = listOfNeighborMap.keySet();
        for (String keys : key) {
            LsaHeader lsaHeader = listOfNeighborMap.get(keys);
            linkStateHeaders.add(lsaHeader);
        }
        return linkStateHeaders;
    }

    /**
     * Gets IP network mask.
     *
     * @return network mask
     */
    public Ip4Address ipNetworkMask() {
        return ipNetworkMask;
    }

    /**
     * Sets IP network mask.
     *
     * @param ipNetworkMask network mask
     */
    @Override
    public void setIpNetworkMask(Ip4Address ipNetworkMask) {
        this.ipNetworkMask = ipNetworkMask;
    }

    /**
     * Adds neighboring router to list.
     *
     * @param ospfNbr ospfNbr instance
     */
    public void addNeighbouringRouter(OspfNbr ospfNbr) {
        listOfNeighbors.put(ospfNbr.neighborId().toString(), ospfNbr);
    }

    /**
     * Gets the neighbour details from listOfNeighbors map.
     *
     * @param neighborId neighbors id
     * @return ospfNbr neighbor instance
     */
    public OspfNbr neighbouringRouter(String neighborId) {
        return listOfNeighbors.get(neighborId);
    }

    /**
     * Removes all the neighbors.
     */
    public void removeNeighbors() {
        Set<String> neighbors = listOfNeighbors.keySet();
        for (String neighborId : neighbors) {
            removeNeighbor(listOfNeighbors.get(neighborId));
            log.debug("Neighbor removed - {}", neighborId);
        }
        listOfNeighbors.clear();
    }

    /**
     * Removes neighbor from the interface neighbor map.
     *
     * @param ospfNeighbor OSPF neighbor instance
     */
    public void removeNeighbor(OspfNbr ospfNeighbor) {
        log.debug("Neighbor removed - {}", ospfNeighbor.neighborId());
        ospfNeighbor.stopInactivityTimeCheck();
        ospfNeighbor.stopFloodingTimer();
        ospfNeighbor.stopRxMtDdTimer();
        ospfNeighbor.stopRxMtLsrTimer();

        listOfNeighbors.remove(ospfNeighbor.neighborId());
    }


    /**
     * Adds LSA header to map.
     *
     * @param lsaHeader LSA header instance
     */
    public void addLsaHeaderForDelayAck(LsaHeader lsaHeader) {
        String key = lsaHeader.lsType() + "-" + lsaHeader.linkStateId() + "-" +
                lsaHeader.advertisingRouter();
        if (lsaHeader.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
                lsaHeader.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
                lsaHeader.lsType() == OspfParameters.AS_OPAQUE_LSA) {
            OpaqueLsaHeader header = (OpaqueLsaHeader) lsaHeader;
            key = lsaHeader.lsType() + "-" + header.opaqueType() + header.opaqueId()
                    + "-" + lsaHeader.advertisingRouter();
        }

        log.debug("Adding LSA key {} for delayed Ack", key);
        listOfNeighborMap.put(key, lsaHeader);
    }

    /**
     * Removes LSA header from map.
     *
     * @param lsaKey key used to store LSA in map
     */
    public void removeLsaFromNeighborMap(String lsaKey) {
        listOfNeighborMap.remove(lsaKey);
    }

    /**
     * Checks neighbor is in the list or not.
     *
     * @param neighborId neighbors id
     * @return true if neighbor in list else false
     */
    public boolean isNeighborInList(String neighborId) {
        return listOfNeighbors.containsKey(neighborId);
    }

    /**
     * Gets the list of neighbors.
     *
     * @return listOfNeighbors as key value pair
     */
    public Map<String, OspfNbr> listOfNeighbors() {
        return listOfNeighbors;
    }

    /**
     * Sets the list of neighbors.
     *
     * @param listOfNeighbors as key value pair
     */
    public void setListOfNeighbors(HashMap<String, OspfNbr> listOfNeighbors) {
        this.listOfNeighbors = listOfNeighbors;
    }

    /**
     * Returns interface index.
     *
     * @return interface index
     */
    public int interfaceIndex() {
        return interfaceIndex;
    }

    /**
     * Set interface index.
     *
     * @param interfaceIndex interface index
     */
    public void setInterfaceIndex(int interfaceIndex) {
        this.interfaceIndex = interfaceIndex;
    }

    /**
     * Gets the IP address.
     *
     * @return IP address
     */
    public Ip4Address ipAddress() {
        return ipAddress;
    }

    /**
     * Sets the interface IP address.
     *
     * @param ipAddress interface IP address
     */
    public void setIpAddress(Ip4Address ipAddress) {
        this.ipAddress = ipAddress;
    }

    /**
     * Gets router priority.
     *
     * @return routerPriority value
     */
    public int routerPriority() {
        return routerPriority;
    }

    /**
     * Sets router priority.
     *
     * @param routerPriority value
     */
    public void setRouterPriority(int routerPriority) {
        this.routerPriority = routerPriority;
    }

    /**
     * Gets hello interval time.
     *
     * @return hello interval time
     */
    public int helloIntervalTime() {
        return helloIntervalTime;
    }

    /**
     * Sets hello interval time.
     *
     * @param helloIntervalTime an integer interval time
     */
    public void setHelloIntervalTime(int helloIntervalTime) {
        this.helloIntervalTime = helloIntervalTime;
    }

    /**
     * Gets router dead interval time.
     *
     * @return router dead interval time
     */
    public int routerDeadIntervalTime() {
        return routerDeadIntervalTime;
    }

    /**
     * Sets router dead interval time.
     *
     * @param routerDeadIntervalTime router dead interval time
     */
    public void setRouterDeadIntervalTime(int routerDeadIntervalTime) {
        this.routerDeadIntervalTime = routerDeadIntervalTime;
    }

    /**
     * Gets interface type.
     *
     * @return interfaceType an integer represents interface type
     */
    public int interfaceType() {
        return interfaceType;
    }

    /**
     * Sets interface type.
     *
     * @param interfaceType interface type
     */
    public void setInterfaceType(int interfaceType) {
        this.interfaceType = interfaceType;
    }

    /**
     * Gets max transfer unit.
     *
     * @return mtu an integer represents max transfer unit
     */
    public int mtu() {
        return mtu;
    }

    /**
     * Sets max transfer unit.
     *
     * @param mtu max transfer unit
     */
    public void setMtu(int mtu) {
        this.mtu = mtu;
    }

    /**
     * Gets retransmit interval.
     *
     * @return retransmit interval
     */
    public int reTransmitInterval() {
        return reTransmitInterval;
    }

    /**
     * Sets retransmit interval.
     *
     * @param reTransmitInterval retransmit interval
     */
    public void setReTransmitInterval(int reTransmitInterval) {
        this.reTransmitInterval = reTransmitInterval;
    }

    /**
     * Gets designated routers IP address.
     *
     * @return dr designated routers IP address
     */
    public Ip4Address dr() {
        return dr;
    }

    /**
     * Sets designated routers IP address.
     *
     * @param dr designated routers IP address
     */
    public void setDr(Ip4Address dr) {
        this.dr = dr;
    }

    /**
     * Gets backup designated routers IP address.
     *
     * @return bdr backup designated routers IP address
     */
    public Ip4Address bdr() {
        return bdr;
    }

    /**
     * Sets backup designated routers IP address.
     *
     * @param bdr backup designated routers IP address
     */
    public void setBdr(Ip4Address bdr) {
        this.bdr = bdr;
    }

    /**
     * Represents an interface is up and connected.
     *
     * @throws Exception might throws exception
     */
    public void interfaceUp() throws Exception {
        log.debug("OSPFInterfaceChannelHandler::interfaceUp...!!!");
        if (interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
            setState(OspfInterfaceState.POINT2POINT);
            interfaceTypeOldValue = interfaceType();
            log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} ",
                      interfaceType(), state());
        } else if (interfaceType() == OspfInterfaceType.BROADCAST.value()) {
            //if router priority is 0, move the state to DROther
            interfaceTypeOldValue = interfaceType();
            if (routerPriority() == 0) {
                setState(OspfInterfaceState.DROTHER);
            } else {
                log.debug("OSPFInterfaceChannelHandler::InterfaceType {} state {} RouterPriority {}",
                          interfaceType(),
                          state(), routerPriority());
                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();
        ospfArea.refreshArea(this);
    }


    /**
     * 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 (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 ");
        //According to RFC-2328 section 9.4
        if (state() == OspfInterfaceState.WAITING) {
            electRouter(ch);
        }
    }

    /**
     * Initiates DR election process.
     *
     * @param ch netty channel instance
     * @throws Exception might throws exception
     */
    public void callDrElection(Channel ch) throws Exception {
        log.debug("OSPFInterfaceChannelHandler::callDrElection ");
        //call when timer expired
        //no hello message received for particular interval
        //section 9.4
        electRouter(ch);
        interfaceTypeOldValue = interfaceType();
    }

    /**
     * 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 (state() == OspfInterfaceState.DR || state() == OspfInterfaceState.BDR ||
                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();
        listOfNeighbors().clear();
        setState(OspfInterfaceState.DOWN);
    }

    /**
     * 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(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 (interfaceType() == OspfInterfaceType.BROADCAST.value() &&
                    !OspfUtil.sameNetwork(((OspfPacketHeader) ospfMessage).sourceIp(),
                                          ipAddress(), 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 {
        Channel channel = ctx.getChannel();
        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 {} ",
                  interfaceType(), state());

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

        if (interfaceType == OspfInterfaceType.POINT_TO_POINT.value() &&
                !helloPacket.dr().equals(OspfUtil.DEFAULTIP)) {
            log.debug("OspfChannelHandler::processHelloMessage:: Neighbor in broadcast network");
            return;
        }

        if (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 (!isNeighborInList(helloPacket.routerId().toString())) {
                nbr = new OspfNbrImpl(ospfArea, this, helloPacket.sourceIp(),
                                      helloPacket.routerId(), helloPacket.options(), topologyForDeviceAndLink);
                addNeighbouringRouter(nbr);
            } else {
                nbr = 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 (interfaceType == OspfInterfaceType.BROADCAST.value()) {

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

                } else if (!helloPacket.dr().equals(Ip4Address.valueOf("0.0.0.0")) ||
                        !helloPacket.bdr().equals(Ip4Address.valueOf("0.0.0.0"))) {
                    setDr(helloPacket.dr());
                    setBdr(helloPacket.bdr());
                }
                Ip4Address sourceIp = helloPacket.sourceIp();
                OspfNbr nbr;
                if (!isNeighborInList(helloPacket.routerId().toString())) {
                    nbr = new OspfNbrImpl(ospfArea, this, sourceIp, helloPacket.routerId(),
                                          helloPacket.options(), topologyForDeviceAndLink);
                    nbr.setNeighborId(helloPacket.routerId());
                    nbr.setNeighborBdr(helloPacket.bdr());
                    nbr.setNeighborDr(helloPacket.dr());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                    addNeighbouringRouter(nbr);
                } else {
                    nbr = 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")))
                        && routerPriority() == 0) {
                    setDr(helloPacket.dr());
                    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 (!isNeighborInList(helloPacket.routerId().toString())) {
                    nbr = new OspfNbrImpl(ospfArea, this, sourceIp, helloPacket.routerId(),
                                          helloPacket.options(), topologyForDeviceAndLink);
                    nbr.setNeighborId(helloPacket.routerId());
                    nbr.setNeighborBdr(helloPacket.bdr());
                    nbr.setNeighborDr(helloPacket.dr());
                    nbr.setRouterPriority(helloPacket.routerPriority());
                    addNeighbouringRouter(nbr);
                    ((OspfNbrImpl) nbr).oneWayReceived(helloPacket, channel);
                } else {
                    log.debug("OspfChannelHandler::NeighborInList::helloPacket.bdr(): {}, " +
                                      "helloPacket.dr(): {}", helloPacket.bdr(), helloPacket.dr());
                    nbr = 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...!!!");
        Channel channel = ctx.getChannel();
        DdPacket ddPacket = (DdPacket) ospfMessage;
        log.debug("Got DD packet from {}", ddPacket.sourceIp());
        //check it is present in listOfNeighbors
        Ip4Address neighbourId = ddPacket.routerId();
        OspfNbr nbr = 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() > 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());
                        byte[] messageToWrite = getMessage(newResPacket);
                        ctx.getChannel().write(messageToWrite);
                    } 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());
                        byte[] messageToWrite = getMessage(newResPacket);
                        ctx.getChannel().write(messageToWrite);
                    } 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());
                                byte[] messageToWrite = getMessage(newResPacket);
                                ctx.getChannel().write(messageToWrite);
                            }
                        } 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());
                                byte[] messageToWrite = getMessage(newResPacket);
                                ctx.getChannel().write(messageToWrite);
                            }
                        }
                    }
                } else {
                    if (masterOrSlave == OspfUtil.NOT_MASTER) {
                        return;
                    } else {
                        DdPacket newResPacket = ((OspfNbrImpl) nbr).lastSentDdPacket();
                        log.debug("Sending back DDPacket to {}", ddPacket.sourceIp());
                        byte[] messageToWrite = getMessage(newResPacket);
                        ctx.getChannel().write(messageToWrite);
                    }
                }
            } 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());
                    byte[] messageToWrite = getMessage(newResPacket);
                    ctx.getChannel().write(messageToWrite);
                } else if (ddPacket.isInitialize() == OspfUtil.INITIALIZE_SET) {
                    OspfMessage newResPacket = ((OspfNbrImpl) nbr).seqNumMismatch("Initialize bit inconsistency");
                    newResPacket.setDestinationIp(ddPacket.sourceIp());
                    byte[] messageToWrite = getMessage(newResPacket);
                    ctx.getChannel().write(messageToWrite);
                }
                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());
                        byte[] messageToWrite = getMessage(((OspfNbrImpl) nbr).lastSentDdPacket());
                        ctx.getChannel().write(messageToWrite);
                        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...!!!");
        Channel channel = ctx.getChannel();
        LsRequest lsrPacket = (LsRequest) ospfMessage;
        OspfNbr nbr = 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 = 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 (state() == OspfInterfaceState.DR ||
                            state() == OspfInterfaceState.BDR ||
                            state() == OspfInterfaceState.POINT2POINT) {
                        lsupdate.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
                    } else if (state() == OspfInterfaceState.DROTHER) {
                        lsupdate.setDestinationIp(OspfUtil.ALL_DROUTERS);
                    }
                    byte[] messageToWrite = getMessage(lsupdate);
                    ctx.getChannel().write(messageToWrite);
                }
            }
        }
    }

    /**
     * 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 (isNeighborInList(neighbourId)) {
            OspfNbrImpl nbr = (OspfNbrImpl) 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) 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 (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;
    }

    /**
     * Starts the hello timer which sends hello packet every configured seconds.
     */
    public void startHelloTimer() {
        log.debug("OSPFInterfaceChannelHandler::startHelloTimer");
        exServiceHello = Executors.newSingleThreadScheduledExecutor();
        helloTimerTask = new InternalHelloTimer();
        final ScheduledFuture<?> helloHandle =
                exServiceHello.scheduleAtFixedRate(helloTimerTask, delay, helloIntervalTime, TimeUnit.SECONDS);
    }

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

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

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

    /**
     * Starts the timer which waits for configured seconds and sends Delayed Ack Packet.
     */
    public 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.
     */
    public 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 = dr();
        Ip4Address currentBdr = bdr();
        OspfInterfaceState oldState = 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);

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

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

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

        if (state() != oldState &&
                !(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);

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

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

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

        if (currentDr != electedDr.getIpAddress() || currentBdr != electedBdr.getIpAddress()) {
            Set<String> negibhorIdList;
            negibhorIdList = listOfNeighbors().keySet();
            for (String routerid : negibhorIdList) {
                OspfNbrImpl nbr = (OspfNbrImpl) 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 = listOfNeighbors().keySet();
        for (String routerId : neighborIdList) {
            OspfNbrImpl nbr = (OspfNbrImpl) 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 (routerPriority() > 0) {
            OspfEligibleRouter router = new OspfEligibleRouter();
            router.setIpAddress(ipAddress());
            router.setRouterId(ospfArea.routerId());
            router.setRouterPriority(routerPriority());
            if (dr().equals(ipAddress()) ||
                    electedDr.getIpAddress().equals(ipAddress())) {
                router.setIsDr(true);
            } else if (bdr().equals(ipAddress()) &&
                    !dr().equals(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 (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 ospfRouter  OSPF router instance
     * @param ospfLinkTed OSPF link TED instance
     */
    public void removeLinkInformation(OspfRouter ospfRouter, OspfLinkTed ospfLinkTed) {
        controller.removeLinkDetails(ospfRouter, ospfLinkTed);
    }

    /**
     * Gets message as bytes.
     *
     * @param ospfMessage OSPF message
     * @return OSPF message
     */
    private byte[] getMessage(OspfMessage ospfMessage) {
        OspfMessageWriter messageWriter = new OspfMessageWriter();
        if (state().equals(OspfInterfaceState.POINT2POINT)) {
            ospfMessage.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
        }
        return (messageWriter.getMessage(ospfMessage, interfaceIndex, state.value()));
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        OspfInterfaceImpl that = (OspfInterfaceImpl) o;
        return Objects.equal(helloIntervalTime, that.helloIntervalTime) &&
                Objects.equal(routerDeadIntervalTime, that.routerDeadIntervalTime) &&
                Objects.equal(routerPriority, that.routerPriority) &&
                Objects.equal(interfaceType, that.interfaceType) &&
                Objects.equal(mtu, that.mtu) &&
                Objects.equal(reTransmitInterval, that.reTransmitInterval) &&
                Objects.equal(ipAddress, that.ipAddress) &&
                Objects.equal(ipNetworkMask, that.ipNetworkMask) &&
                Objects.equal(listOfNeighbors, that.listOfNeighbors) &&
                Objects.equal(dr, that.dr) &&
                Objects.equal(bdr, that.bdr);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(ipAddress, ipNetworkMask, helloIntervalTime,
                                routerDeadIntervalTime, routerPriority, listOfNeighbors,
                                interfaceType, mtu, reTransmitInterval, dr, bdr);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("ipAddress", ipAddress)
                .add("routerPriority", routerPriority)
                .add("helloIntervalTime", helloIntervalTime)
                .add("routerDeadIntervalTime", routerDeadIntervalTime)
                .add("interfaceType", interfaceType)
                .add("mtu", mtu)
                .add("reTransmitInterval", reTransmitInterval)
                .add("dr", dr)
                .add("bdr", bdr)
                .toString();
    }

    /**
     * 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 (channel != null && channel.isOpen() && channel.isConnected()) {
                if (interfaceType() == OspfInterfaceType.BROADCAST.value()) {
                    if (interfaceTypeOldValue != interfaceType()) {
                        try {
                            callDrElection(channel);
                        } catch (Exception e) {
                            log.debug("Error while calling interfaceUp {}", e.getMessage());
                        }
                    }
                } else {
                    if (interfaceTypeOldValue != interfaceType()) {
                        interfaceTypeOldValue = interfaceType();
                    }
                }
                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(OspfUtil.NOT_ASSIGNED);
                hellopacket.setAuthentication(OspfUtil.NOT_ASSIGNED);
                //Body
                hellopacket.setNetworkMask(ipNetworkMask());
                hellopacket.setOptions(ospfArea.options());
                hellopacket.setHelloInterval(helloIntervalTime());
                hellopacket.setRouterPriority(routerPriority());
                hellopacket.setRouterDeadInterval(routerDeadIntervalTime());
                hellopacket.setDr(dr());
                hellopacket.setBdr(bdr());

                Map<String, OspfNbr> listOfNeighbors = 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);
                byte[] messageToWrite = getMessage(hellopacket);
                ChannelFuture future = channel.write(messageToWrite);
                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 (!linkStateHeaders().isEmpty()) {
                isDelayedAckTimerScheduled = true;
                if (ch != null && ch.isConnected()) {

                    List<LsaHeader> listOfLsaHeadersAcknowledged = new ArrayList<>();
                    List<LsaHeader> listOfLsaHeaders = 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 = 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 (state() == OspfInterfaceState.DR || state() == OspfInterfaceState.BDR
                                || state() == OspfInterfaceState.POINT2POINT) {
                            ackContent.setDestinationIp(OspfUtil.ALL_SPF_ROUTERS);
                        } else if (state() == OspfInterfaceState.DROTHER) {
                            ackContent.setDestinationIp(OspfUtil.ALL_DROUTERS);
                        }
                        byte[] messageToWrite = getMessage(ackContent);
                        ch.write(messageToWrite);

                        for (LsaHeader lsa : listOfLsaHeadersAcknowledged) {
                            linkStateHeaders().remove(lsa);
                            removeLsaFromNeighborMap(((OspfAreaImpl) ospfArea).getLsaKey(lsa));
                        }
                    }
                }
            }
        }
    }
}