/*
 * 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.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);
    /**
     * Whether AS-external-LSAs will be flooded into/throughout the area.
     */
    private boolean externalRoutingCapability;

    /**
     * Represents a list of all router's interfaces associated with this area.
     */
    private List<OspfInterface> ospfInterfaceList;
    /**
     * 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(externalRoutingCapability, that.externalRoutingCapability) &&
                Objects.equal(ospfInterfaceList.size(), that.ospfInterfaceList.size()) &&
                Objects.equal(database, that.database);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(areaId, routerId, externalRoutingCapability,
                                ospfInterfaceList, 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 = ospfInterfaceList.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 = ospfInterfaceList.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 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 list of interfaces in this area.
     *
     * @return list of interfaces
     */
    public List<OspfInterface> ospfInterfaceList() {
        return ospfInterfaceList;
    }

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

    /**
     * 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 = ospfInterfaceList.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("ospfInterfaceList", ospfInterfaceList)
                .add("externalRoutingCapability", externalRoutingCapability)
                .toString();
    }

    /**
     * Checks all Neighbors belonging to this Area whether they are in state lesser than the EXCHANGE.
     * Creates list of such neighbors
     * 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 = ospfInterfaceList();
        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;
    }
}