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

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import org.onlab.packet.Ip4Address;
import org.onosproject.ospf.controller.LsaWrapper;
import org.onosproject.ospf.controller.OspfArea;
import org.onosproject.ospf.controller.OspfAreaAddressRange;
import org.onosproject.ospf.controller.OspfInterface;
import org.onosproject.ospf.controller.OspfLsa;
import org.onosproject.ospf.controller.OspfLsaType;
import org.onosproject.ospf.controller.OspfLsdb;
import org.onosproject.ospf.controller.OspfNbr;
import org.onosproject.ospf.controller.OspfNeighborState;
import org.onosproject.ospf.controller.impl.OspfNbrImpl;
import org.onosproject.ospf.controller.lsdb.OspfLsdbImpl;
import org.onosproject.ospf.protocol.lsa.LsaHeader;
import org.onosproject.ospf.protocol.lsa.subtypes.OspfLsaLink;
import org.onosproject.ospf.protocol.lsa.types.NetworkLsa;
import org.onosproject.ospf.protocol.lsa.types.RouterLsa;
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.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Representation an OSPF area and related information.
 */
public class OspfAreaImpl implements OspfArea {
    private static final Logger log = LoggerFactory.getLogger(OspfAreaImpl.class);
    /**
     * Address ranges in order to aggregate routing information at area.
     * boundaries. Each address range is specified by an [address,mask] pair and
     * a status indication of either Advertise or DoNotAdvertise
     */
    private List<OspfAreaAddressRange> addressRanges;
    /**
     * This parameter indicates whether the area can carry data traffic that.
     * neither originates nor terminates in the area itself.
     */
    private boolean transitCapability;
    /**
     * Whether AS-external-LSAs will be flooded into/throughout the area.
     */
    private boolean externalRoutingCapability;
    /**
     * Indicates the cost of the default summary-LSA.
     */
    private int stubCost;
    /**
     * Represents a list of all router's interfaces associated with this area.
     */
    private List<OspfInterface> interfacesLst;
    /**
     * The LS Database for this area. It includes router-LSAs, network-LSAs and.
     * summary-LSAs. AS-external-LSAs are hold in the OSPF class itself.
     */
    private OspfLsdbImpl database;
    /**
     * A 32-bit number identifying the area.
     */
    private Ip4Address areaId;
    /**
     * Router ID.
     */
    private Ip4Address routerId;
    /**
     * Represents Options like external, opaque capabilities.
     */
    private int options;
    /**
     * Represents Opaque Enable or not.
     */
    private boolean isOpaqueEnable;

    /**
     * Creates an instance of area implementation.
     */
    public OspfAreaImpl() {
        database = new OspfLsdbImpl(this);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        OspfAreaImpl that = (OspfAreaImpl) o;
        return Objects.equal(areaId, that.areaId) &&
                Objects.equal(routerId, that.routerId) &&
                Objects.equal(addressRanges.size(), that.addressRanges.size()) &&
                Objects.equal(transitCapability, that.transitCapability) &&
                Objects.equal(externalRoutingCapability, that.externalRoutingCapability) &&
                Objects.equal(stubCost, that.stubCost) &&
                Objects.equal(interfacesLst.size(), that.interfacesLst.size()) &&
                Objects.equal(database, that.database);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(areaId, routerId, addressRanges, transitCapability, externalRoutingCapability,
                                stubCost, interfacesLst, database);
    }

    /**
     * Gets the router id.
     *
     * @return router id
     */
    public Ip4Address routerId() {
        return routerId;
    }

    /**
     * Sets the router id.
     *
     * @param routerId router id
     */
    @JsonProperty("routerId")
    public void setRouterId(Ip4Address routerId) {
        this.routerId = routerId;
    }

    /**
     * Sets opaque enabled to true or false.
     *
     * @param isOpaqueEnable true if opaque enabled else false
     */
    @JsonProperty("isOpaqueEnable")
    public void setIsOpaqueEnabled(boolean isOpaqueEnable) {
        this.isOpaqueEnable = isOpaqueEnable;
    }

    /**
     * Gets is opaque enabled or not.
     *
     * @return true if opaque enabled else false
     */
    public boolean isOpaqueEnabled() {
        return this.isOpaqueEnable;
    }

    /**
     * Initializes link state database.
     */
    public void initializeDb() {

        database.initializeDb();
    }

    /**
     * Refreshes the OSPF area information .
     * Gets called as soon as the interface is down or neighbor full Router LSA is updated.
     *
     * @param ospfInterface OSPF interface instance
     */
    @Override
    public void refreshArea(OspfInterface ospfInterface) {
        OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
        log.debug("Inside refreshArea...!!!");
        //If interface state is DR build network LSA.
        if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
            if (ospfInterface.listOfNeighbors().size() > 0) {
                //Get the NetworkLsa
                NetworkLsa networkLsa = null;
                try {
                    networkLsa = buildNetworkLsa(ospfInterface.ipAddress(), ospfInterface.ipNetworkMask());
                } catch (Exception e) {
                    log.debug("Error while building NetworkLsa {}", e.getMessage());
                }
                //Add the NetworkLsa to lsdb
                database.addLsa(networkLsa, true, ospfInterface);
                addToOtherNeighborLsaTxList(networkLsa);
            } else {
                log.debug("No Neighbors hence not creating  NetworkLSA...!!!");
            }
        }
        //Get the router LSA
        RouterLsa routerLsa = null;
        try {
            routerLsa = buildRouterLsa(ospfInterface);
        } catch (Exception e) {
            log.debug("Error while building RouterLsa {}", e.getMessage());
        }
        //Add the RouterLSA to lsdb
        database.addLsa(routerLsa, true, ospfInterface);
        addToOtherNeighborLsaTxList(routerLsa);
    }

    /**
     * Builds a network LSA.
     *
     * @param interfaceIp interface IP address
     * @param mask        interface network mask
     * @return NetworkLsa instance
     * @throws Exception might throws exception
     */
    public NetworkLsa buildNetworkLsa(Ip4Address interfaceIp, Ip4Address mask) throws Exception {
        // generate the Router-LSA for this Area.
        NetworkLsa networkLsa = new NetworkLsa();
        networkLsa.setAdvertisingRouter(routerId);
        networkLsa.setLinkStateId(interfaceIp.toString());
        networkLsa.setLsType(OspfLsaType.NETWORK.value());
        networkLsa.setAge(1);
        networkLsa.setOptions(2);
        networkLsa.setNetworkMask(mask);
        //Adding our own router.
        networkLsa.addAttachedRouter(routerId());
        Iterator iter = interfacesLst.iterator();
        OspfInterfaceImpl ospfInterface = null;
        while (iter.hasNext()) {
            ospfInterface = (OspfInterfaceImpl) iter.next();
            if (ospfInterface.ipAddress().equals(interfaceIp)) {
                break;
            }
        }
        if (ospfInterface != null) {
            List<OspfNbr> neighborsInFullState = getNeighborsInFullState(ospfInterface);
            if (neighborsInFullState != null) {
                for (OspfNbr ospfnbr : neighborsInFullState) {
                    networkLsa.addAttachedRouter(ospfnbr.neighborId());
                    log.debug("Adding attached neighbor:: {}", ospfnbr.neighborId());
                }
            }
        }
        networkLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.NETWORK));
        //Find the byte length and add it in lsa object
        ChecksumCalculator checksum = new ChecksumCalculator();
        byte[] lsaBytes = networkLsa.asBytes();
        networkLsa.setLsPacketLen(lsaBytes.length);
        //Convert lsa object to byte again to reflect the packet length which we added.
        lsaBytes = networkLsa.asBytes();
        //find the checksum
        byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
                                                               OspfUtil.LSAPACKET_CHECKSUM_POS1,
                                                               OspfUtil.LSAPACKET_CHECKSUM_POS2);
        int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
        networkLsa.setLsCheckSum(checkSumVal);
        return networkLsa;
    }

    /**
     * Builds Router LSA.
     *
     * @param ospfInterface Interface instance
     * @return routerLsa Router LSA instance
     * @throws Exception might throws exception
     */
    public RouterLsa buildRouterLsa(OspfInterface ospfInterface) throws Exception {
        // generate the Router-LSA for this Area.
        RouterLsa routerLsa = new RouterLsa();
        routerLsa.setAdvertisingRouter(routerId);
        routerLsa.setLinkStateId(routerId.toString());
        routerLsa.setLsType(OspfLsaType.ROUTER.value());
        routerLsa.setAge(1);
        routerLsa.setOptions(options);
        routerLsa.setAreaBorderRouter(false);
        routerLsa.setAsBoundaryRouter(false);
        routerLsa.setVirtualEndPoint(false);
        buildLinkForRouterLsa(routerLsa, ospfInterface);
        routerLsa.setLsSequenceNo(database.getLsSequenceNumber(OspfLsaType.ROUTER));
        //Find the byte length and add it in lsa object
        ChecksumCalculator checksum = new ChecksumCalculator();
        byte[] lsaBytes = routerLsa.asBytes();
        routerLsa.setLsPacketLen(lsaBytes.length);
        //Convert lsa object to byte again to reflect the packet length whic we added.
        lsaBytes = routerLsa.asBytes();
        //find the checksum
        byte[] twoByteChecksum = checksum.calculateLsaChecksum(lsaBytes,
                                                               OspfUtil.LSAPACKET_CHECKSUM_POS1,
                                                               OspfUtil.LSAPACKET_CHECKSUM_POS2);
        int checkSumVal = OspfUtil.byteToInteger(twoByteChecksum);
        routerLsa.setLsCheckSum(checkSumVal);
        return routerLsa;
    }

    /**
     * Builds LSA link for router LSA.
     *
     * @param routerLsa     router LSA instance
     * @param ospfInterface interface instance
     */
    private void buildLinkForRouterLsa(RouterLsa routerLsa, OspfInterface ospfInterface) {
        OspfInterfaceImpl nextInterface;
        Iterator interfaces = interfacesLst.iterator();
        while (interfaces.hasNext()) {
            nextInterface = (OspfInterfaceImpl) interfaces.next();
            if (nextInterface.state() == OspfInterfaceState.DOWN) {
                continue;
            } else if (nextInterface.state() == OspfInterfaceState.LOOPBACK) {
                OspfLsaLink link = new OspfLsaLink();
                link.setLinkData("-1");
                link.setLinkId(nextInterface.ipAddress().toString());
                link.setLinkType(3);
                link.setMetric(0);
                link.setTos(0);
                routerLsa.addRouterLink(link);
                routerLsa.incrementLinkNo();
            } else if (nextInterface.state() == OspfInterfaceState.POINT2POINT) {
                // adding all neighbour routers
                List<OspfNbr> neighborsInFullState = getNeighborsInFullState(nextInterface);
                if (neighborsInFullState != null) {
                    log.debug("Adding OspfLsaLink ::neighborsInFullState {}, InterfaceIP: {}",
                              neighborsInFullState.size(), nextInterface.ipAddress());
                    for (OspfNbr ospfnbr : neighborsInFullState) {
                        OspfLsaLink link = new OspfLsaLink();
                        link.setLinkData(nextInterface.ipAddress().toString());
                        link.setLinkId(ospfnbr.neighborId().toString());
                        link.setLinkType(1);
                        link.setMetric(0);
                        link.setTos(0);
                        routerLsa.addRouterLink(link);
                        routerLsa.incrementLinkNo();
                        log.debug("Added OspfLsaLink :: {}, neighborIP: {}, routerLinks: {}",
                                  ospfnbr.neighborId(), ospfnbr.neighborIpAddr(), routerLsa.noLink());
                    }
                }
                // adding the self address
                OspfLsaLink link = new OspfLsaLink();
                link.setLinkData(nextInterface.ipNetworkMask().toString());
                link.setLinkId(nextInterface.ipAddress().toString());
                link.setLinkType(3);
                link.setMetric(0);
                link.setTos(0);
                routerLsa.addRouterLink(link);
                routerLsa.incrementLinkNo();
            } else {
                buildLinkForRouterLsaBroadcast(routerLsa, nextInterface);
            }
        }
    }

    /**
     * Builds LSA link for router LSA.
     *
     * @param routerLsa     router LSA instance
     * @param ospfInterface interface instance
     */
    private void buildLinkForRouterLsaBroadcast(RouterLsa routerLsa, OspfInterface ospfInterface) {
        OspfInterfaceImpl ospfInterfaceImpl = (OspfInterfaceImpl) ospfInterface;
        if (ospfInterfaceImpl.state() == OspfInterfaceState.WAITING) {
            OspfLsaLink link = new OspfLsaLink();
            link.setLinkData(ospfInterface.ipNetworkMask().toString());
            //Link id should be set to ip network number
            link.setLinkId(ospfInterface.ipAddress().toString());
            link.setLinkType(3);
            link.setMetric(0);
            link.setTos(0);
            routerLsa.addRouterLink(link);
            routerLsa.incrementLinkNo();
        } else if (ospfInterfaceImpl.state() == OspfInterfaceState.DR) {
            OspfLsaLink link = new OspfLsaLink();
            link.setLinkData(ospfInterface.ipAddress().toString());
            link.setLinkId(ospfInterface.ipAddress().toString());
            link.setLinkType(2);
            link.setMetric(0);
            link.setTos(0);
            routerLsa.addRouterLink(link);
            routerLsa.incrementLinkNo();
        } else if (ospfInterfaceImpl.state() == OspfInterfaceState.BDR ||
                ospfInterfaceImpl.state() == OspfInterfaceState.DROTHER) {
            OspfLsaLink link = new OspfLsaLink();
            link.setLinkData(ospfInterface.ipAddress().toString());
            link.setLinkId(ospfInterface.dr().toString());
            link.setLinkType(2);
            link.setMetric(0);
            link.setTos(0);
            routerLsa.addRouterLink(link);
            routerLsa.incrementLinkNo();
        }
    }

    /**
     * Gets the area id.
     *
     * @return area id
     */
    public Ip4Address areaId() {
        return areaId;
    }

    /**
     * Sets the area id.
     *
     * @param areaId area id
     */
    @JsonProperty("areaId")
    public void setAreaId(Ip4Address areaId) {
        this.areaId = areaId;
    }

    /**
     * Gets address range.
     *
     * @return list of area address ranges
     */
    public List<OspfAreaAddressRange> addressRanges() {
        return addressRanges;
    }

    /**
     * Sets the area address ranges.
     *
     * @param addressRanges list of area address range
     */
    @JsonProperty("addressRange")
    public void setAddressRanges(List<OspfAreaAddressRange> addressRanges) {
        this.addressRanges = addressRanges;
    }

    /**
     * Gets is transit capable or not.
     *
     * @return true if transit capable, else false
     */
    public boolean isTransitCapability() {
        return transitCapability;
    }

    /**
     * Sets transit capability.
     *
     * @param transitCapability true if transit capable, else false
     */
    @JsonProperty("transitCapability")
    public void setTransitCapability(boolean transitCapability) {
        this.transitCapability = transitCapability;
    }

    /**
     * Gets external routing capability.
     *
     * @return true if external routing capable, else false
     */
    public boolean isExternalRoutingCapability() {
        return externalRoutingCapability;
    }

    /**
     * Sets external routing capability.
     *
     * @param externalRoutingCapability true if external routing capable, else false
     */
    @JsonProperty("externalRoutingCapability")
    public void setExternalRoutingCapability(boolean externalRoutingCapability) {
        this.externalRoutingCapability = externalRoutingCapability;
    }

    /**
     * Gets the stub cost.
     *
     * @return stub cost
     */
    public int stubCost() {
        return stubCost;
    }

    /**
     * Sets the stub cost.
     *
     * @param stubCost stub cost
     */
    @JsonProperty("stubCost")
    public void setStubCost(int stubCost) {
        this.stubCost = stubCost;
    }

    /**
     * Gets the list of interfaces in this area.
     *
     * @return list of interfaces
     */
    public List<OspfInterface> getInterfacesLst() {
        return interfacesLst;
    }

    /**
     * Sets the list of interfaces attached to the area.
     *
     * @param interfacesLst list of OspfInterface instances
     */
    @JsonProperty("interface")
    public void setInterfacesLst(List<OspfInterface> interfacesLst) {
        this.interfacesLst = interfacesLst;
    }

    /**
     * Checks all neighbors belonging to this area whether they are in state EXCHANGE or LOADING.
     * Return false if there is at least one, else return true. This Method is used by
     * "processReceivedLsa()" in the neighbor class.
     *
     * @return boolean indicating that there is no Neighbor in Database Exchange
     */
    public boolean noNeighborInLsaExchangeProcess() {
        OspfInterfaceImpl nextInterface;
        OspfNeighborState nextNeighborState;
        Iterator interfaces = interfacesLst.iterator();
        while (interfaces.hasNext()) {
            nextInterface = (OspfInterfaceImpl) interfaces.next();
            Iterator neighbors = nextInterface.listOfNeighbors().values().iterator();
            while (neighbors.hasNext()) {
                nextNeighborState = ((OspfNbrImpl) neighbors.next()).getState();
                if (nextNeighborState == OspfNeighborState.EXCHANGE ||
                        nextNeighborState == OspfNeighborState.LOADING) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * Gets header of all types of LSAs.
     *
     * @param excludeMaxAgeLsa need to include(true) or exclude(false) maxage lsa's
     * @param isOpaquecapable  need to include(true) or exclude(false) Type 10 Opaque lsa's
     * @return list of lsa header in the lsdb
     */
    public List getLsaHeaders(boolean excludeMaxAgeLsa, boolean isOpaquecapable) {
        return database.getAllLsaHeaders(excludeMaxAgeLsa, isOpaquecapable);
    }

    /**
     * Gets the LSA from LSDB based on the input.
     *
     * @param lsType            type of lsa to form the key
     * @param linkStateID       link state id to form the key
     * @param advertisingRouter advertising router to form the key
     * @return lsa wrapper instance which contains the Lsa
     * @throws Exception might throws exception
     */
    public LsaWrapper getLsa(int lsType, String linkStateID, String advertisingRouter) throws Exception {
        String lsaKey = lsType + "-" + linkStateID + "-" + advertisingRouter;
        if (lsType == OspfParameters.LINK_LOCAL_OPAQUE_LSA || lsType == OspfParameters.AREA_LOCAL_OPAQUE_LSA ||
                lsType == OspfParameters.AS_OPAQUE_LSA) {
            byte[] linkStateAsBytes = InetAddress.getByName(linkStateID).getAddress();
            int opaqueType = linkStateAsBytes[0];
            int opaqueId = OspfUtil.byteToInteger(Arrays.copyOfRange(linkStateAsBytes, 1,
                                                                     linkStateAsBytes.length));
            lsaKey = lsType + "-" + opaqueType + opaqueId + "-" + advertisingRouter;
        }
        return database.findLsa(lsType, lsaKey);
    }


    /**
     * Checks whether an instance of the given LSA exists in the database belonging to this area.
     * If so return true else false.
     *
     * @param lookupLsa ospf LSA instance to lookup
     * @return LSA wrapper instance which contains the Lsa
     */
    public LsaWrapper lsaLookup(OspfLsa lookupLsa) {
        return database.lsaLookup((LsaHeader) lookupLsa);
    }

    /**
     * Checks whether an instance of the given LSA exists in the database belonging to this area.
     * If so return true else false.
     *
     * @param lsa1 OSPF LSA instance to compare
     * @param lsa2 OSPF LSA instance to compare
     * @return "same" if both instances are same, "latest" if lsa1 is latest, or "old" if lsa1 is old
     */
    public String isNewerOrSameLsa(OspfLsa lsa1, OspfLsa lsa2) {
        return database.isNewerOrSameLsa((LsaHeader) lsa1, (LsaHeader) lsa2);
    }

    /**
     * Methods gets called from ChannelHandler to add the received LSA to LSDB.
     *
     * @param ospfLsa       OSPF LSA instance
     * @param ospfInterface OSPF interface instance
     */
    public void addLsa(OspfLsa ospfLsa, OspfInterface ospfInterface) throws Exception {
        //second param is false as lsa from network
        database.addLsa((LsaHeader) ospfLsa, false, ospfInterface);
    }

    /**
     * Methods gets called from ChannelHandler to add the received LSA to LSDB.
     *
     * @param ospfLsa          OSPF LSA instance
     * @param isSelfOriginated true if the LSA is self originated. Else false
     * @param ospfInterface    OSPF interface instance
     */
    public void addLsa(OspfLsa ospfLsa, boolean isSelfOriginated, OspfInterface ospfInterface)
            throws Exception {
        database.addLsa((LsaHeader) ospfLsa, isSelfOriginated, ospfInterface);
    }

    /**
     * Adds the LSA to maxAge bin.
     *
     * @param key     key to add it to LSDB
     * @param wrapper LSA wrapper instance
     */
    public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
        database.addLsaToMaxAgeBin(key, wrapper);
    }

    /**
     * Sets router sequence number for router LSA.
     *
     * @param newSequenceNumber sequence number
     */
    public void setDbRouterSequenceNumber(long newSequenceNumber) {
        database.setRouterLsaSeqNo(newSequenceNumber);
    }

    /**
     * Methods gets called from ChannelHandler to delete the LSA.
     *
     * @param ospfLsa the LSA instance to delete
     */
    public void deleteLsa(LsaHeader ospfLsa) {
        database.deleteLsa(ospfLsa);
    }

    /**
     * Removes LSA from bin.
     *
     * @param lsaWrapper the LSA wrapper instance to delete
     */
    public void removeLsaFromBin(LsaWrapper lsaWrapper) {
        database.removeLsaFromBin(lsaWrapper);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(getClass())
                .omitNullValues()
                .add("areaID", areaId)
                .add("stubCost", stubCost)
                .add("addressRanges", addressRanges)
                .add("interfacesLst", interfacesLst)
                .add("transitCapability", transitCapability)
                .add("externalRoutingCapability", externalRoutingCapability)
                .toString();
    }

    /**
     * Checks all Neighbors belonging to this Area whether they are in state lesser than the EXCHANGE.
     * <p>
     * Creates list of such neighbors
     * <p>
     * Returns list of neighbors who satisfy the conditions
     *
     * @param ospfInterface OSPF interface instance
     * @return List of interfaces having state lesser than exchange
     */
    public List<OspfNbr> getNeighborsInFullState(OspfInterface ospfInterface) {

        List<OspfNbr> listEligibleNeighbors = null;
        OspfNbrImpl ospfNeighbor = null;
        OspfNeighborState nextNeighborState;
        Iterator nbrInterface = ospfInterface.listOfNeighbors().values().iterator();
        while (nbrInterface.hasNext()) {
            ospfNeighbor = (OspfNbrImpl) nbrInterface.next();
            nextNeighborState = ospfNeighbor.getState();
            if (nextNeighborState.getValue() == OspfNeighborState.FULL.getValue()) {
                if (listEligibleNeighbors == null) {
                    listEligibleNeighbors = new ArrayList<OspfNbr>();
                    listEligibleNeighbors.add(ospfNeighbor);
                } else {
                    listEligibleNeighbors.add(ospfNeighbor);
                }
            }
        }
        return listEligibleNeighbors;
    }

    /**
     * Gets the LSDB LSA key from LSA header.
     *
     * @param lsaHeader LSA header instance
     * @return key LSA key
     */
    public String getLsaKey(LsaHeader lsaHeader) {
        return database.getLsaKey(lsaHeader);
    }

    /**
     * Adds the received LSA in other neighbors tx list.
     *
     * @param recLsa LSA Header instance
     */
    public void addToOtherNeighborLsaTxList(LsaHeader recLsa) {
        //Add the received LSA in other neighbors retransmission list.
        log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList");
        List<OspfInterface> ospfInterfaces = getInterfacesLst();
        for (OspfInterface ospfInterfaceFromArea : ospfInterfaces) {
            Map neighbors = ospfInterfaceFromArea.listOfNeighbors();
            for (Object neighborIP : neighbors.keySet()) {
                OspfNbrImpl nbr = (OspfNbrImpl) neighbors.get(neighborIP);
                if (nbr.getState().getValue() < OspfNeighborState.EXCHANGE.getValue()) {
                    continue;
                }
                String key = database.getLsaKey(recLsa);
                if (nbr.getState() == OspfNeighborState.EXCHANGE || nbr.getState() == OspfNeighborState.LOADING) {
                    if (nbr.getLsReqList().containsKey(key)) {
                        LsaWrapper lsWrapper = lsaLookup(recLsa);
                        if (lsWrapper != null) {
                            LsaHeader ownLSA = (LsaHeader) lsWrapper.ospfLsa();
                            String status = isNewerOrSameLsa(recLsa, ownLSA);
                            if (status.equals("old")) {
                                continue;
                            } else if (status.equals("same")) {
                                log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
                                                  "Removing lsa from reTxtList {}", key);
                                nbr.getLsReqList().remove(key);
                                continue;
                            } else {
                                log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: " +
                                                  "Removing lsa from reTxtList {}", key);
                                nbr.getLsReqList().remove(key);
                            }
                        }
                    }
                }
                if (recLsa.advertisingRouter().equals((String) neighborIP)) {
                    continue;
                }
                if ((recLsa.lsType() == OspfParameters.LINK_LOCAL_OPAQUE_LSA ||
                        recLsa.lsType() == OspfParameters.AREA_LOCAL_OPAQUE_LSA)) {
                    if (nbr.isOpaqueCapable()) {
                        log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
                                  recLsa);
                        nbr.getReTxList().put(key, recLsa);
                    }
                } else {
                    log.debug("OspfAreaImpl: addToOtherNeighborLsaTxList: Adding lsa to reTxtList {}",
                              recLsa);
                    nbr.getReTxList().put(key, recLsa);
                }
            }
        }
    }

    /**
     * Gets the options value.
     *
     * @return options value
     */
    public int options() {
        return options;
    }

    /**
     * Sets the options value.
     *
     * @param options options value
     */
    public void setOptions(int options) {
        this.options = options;
    }

    /**
     * Gets the opaque enabled options value.
     *
     * @return opaque enabled options value
     */
    public int opaqueEnabledOptions() {
        return Integer.parseInt(OspfParameters.OPAQUE_ENABLED_OPTION_VALUE, 2);
    }

    /**
     * Gets the lsdb instance for this area.
     *
     * @return lsdb instance
     */
    public OspfLsdb database() {
        return database;
    }
}