/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.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;
    }
}