/*
 * 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.isis.controller.impl;

import org.jboss.netty.channel.Channel;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onosproject.isis.controller.IsisInterface;
import org.onosproject.isis.controller.IsisInterfaceState;
import org.onosproject.isis.controller.IsisLsdb;
import org.onosproject.isis.controller.IsisMessage;
import org.onosproject.isis.controller.IsisNeighbor;
import org.onosproject.isis.controller.IsisNetworkType;
import org.onosproject.isis.controller.IsisPduType;
import org.onosproject.isis.controller.IsisRouterType;
import org.onosproject.isis.controller.LspWrapper;
import org.onosproject.isis.io.isispacket.IsisHeader;
import org.onosproject.isis.io.isispacket.pdu.Csnp;
import org.onosproject.isis.io.isispacket.pdu.HelloPdu;
import org.onosproject.isis.io.isispacket.pdu.L1L2HelloPdu;
import org.onosproject.isis.io.isispacket.pdu.LsPdu;
import org.onosproject.isis.io.isispacket.pdu.P2PHelloPdu;
import org.onosproject.isis.io.isispacket.pdu.Psnp;
import org.onosproject.isis.io.isispacket.tlv.AdjacencyStateTlv;
import org.onosproject.isis.io.isispacket.tlv.IsisTlv;
import org.onosproject.isis.io.isispacket.tlv.LspEntriesTlv;
import org.onosproject.isis.io.isispacket.tlv.LspEntry;
import org.onosproject.isis.io.isispacket.tlv.TlvHeader;
import org.onosproject.isis.io.isispacket.tlv.TlvType;
import org.onosproject.isis.io.util.IsisConstants;
import org.onosproject.isis.io.util.IsisUtil;
import org.onosproject.isis.io.util.LspGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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 ISIS interface.
 */
public class DefaultIsisInterface implements IsisInterface {
    private static final Logger log = LoggerFactory.getLogger(DefaultIsisInterface.class);
    boolean flagValue = false;
    private int interfaceIndex;
    private Ip4Address interfaceIpAddress;
    private byte[] networkMask;
    private MacAddress interfaceMacAddress;
    private String intermediateSystemName;
    private String systemId;
    private String l1LanId;
    private String l2LanId;
    private int idLength;
    private int maxAreaAddresses;
    private int reservedPacketCircuitType;
    private IsisNetworkType networkType;
    private String areaAddress;
    private int areaLength;
    private String lspId;
    private int holdingTime;
    private int priority;
    private String circuitId;
    private int helloInterval;
    private Map<MacAddress, IsisNeighbor> neighborList = new ConcurrentHashMap<>();
    private IsisHelloPduSender isisHelloPduSender = null;
    private ScheduledExecutorService exServiceHello = null;
    private IsisInterfaceState interfaceState = IsisInterfaceState.DOWN;
    private IsisLsdb isisLsdb = null;
    private List<Ip4Address> allConfiguredInterfaceIps = null;
    private Channel channel;

    /**
     * Returns ISIS LSDB instance.
     *
     * @return ISIS LSDB instance
     */
    public IsisLsdb isisLsdb() {
        return isisLsdb;
    }

    /**
     * Sets all configured interface IPs.
     *
     * @param allConfiguredInterfaces all configured interface IPs
     */
    public void setAllConfiguredInterfaceIps(List<Ip4Address> allConfiguredInterfaces) {
        allConfiguredInterfaceIps = allConfiguredInterfaces;
    }

    /**
     * Removes neighbor from the interface neighbor map.
     *
     * @param isisNeighbor ISIS neighbor instance
     */
    public void removeNeighbor(IsisNeighbor isisNeighbor) {
        neighborList.remove(isisNeighbor.neighborMacAddress());
    }

    /**
     * Returns the ISIS neighbor instance if exists.
     *
     * @param isisNeighborMac mac address of the neighbor router
     * @return ISIS neighbor instance if exists else null
     */
    public IsisNeighbor lookup(MacAddress isisNeighborMac) {
        return neighborList.get(isisNeighborMac);
    }

    /**
     * Returns the neighbors list.
     *
     * @return neighbors list
     */
    public Set<MacAddress> neighbors() {
        return neighborList.keySet();
    }

    /**
     * Returns channel instance.
     *
     * @return channel instance
     */
    public Channel channel() {
        return channel;
    }

    /**
     * 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;
    }

    /**
     * Returns the interface IP address.
     *
     * @return interface IP address
     */
    public Ip4Address interfaceIpAddress() {
        return interfaceIpAddress;
    }

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

    /**
     * Returns the network mask.
     *
     * @return network mask
     */
    public byte[] networkMask() {
        return networkMask;
    }

    /**
     * Sets the network mask.
     *
     * @param networkMask network mask
     */
    public void setNetworkMask(byte[] networkMask) {
        this.networkMask = networkMask;
    }

    /**
     * Returns the interface mac address.
     *
     * @return interface mac address
     */
    public MacAddress getInterfaceMacAddress() {
        return interfaceMacAddress;
    }

    /**
     * Sets the interface mac address.
     *
     * @param interfaceMacAddress interface mac address
     */
    public void setInterfaceMacAddress(MacAddress interfaceMacAddress) {
        this.interfaceMacAddress = interfaceMacAddress;
    }

    /**
     * Returns intermediate system name.
     *
     * @return intermediate system name
     */
    public String intermediateSystemName() {
        return intermediateSystemName;
    }

    /**
     * Sets intermediate system name.
     *
     * @param intermediateSystemName intermediate system name
     */
    public void setIntermediateSystemName(String intermediateSystemName) {
        this.intermediateSystemName = intermediateSystemName;
    }

    /**
     * Returns system ID.
     *
     * @return system ID
     */
    public String systemId() {
        return systemId;
    }

    /**
     * Sets system ID.
     *
     * @param systemId system ID
     */
    public void setSystemId(String systemId) {
        this.systemId = systemId;
    }

    /**
     * Returns LAN ID.
     *
     * @return LAN ID
     */
    public String l1LanId() {
        return l1LanId;
    }

    /**
     * Sets LAN ID.
     *
     * @param l1LanId LAN ID
     */
    public void setL1LanId(String l1LanId) {
        this.l1LanId = l1LanId;
    }

    /**
     * Returns LAN ID.
     *
     * @return LAN ID
     */
    public String l2LanId() {
        return l2LanId;
    }

    /**
     * Sets LAN ID.
     *
     * @param l2LanId LAN ID
     */
    public void setL2LanId(String l2LanId) {
        this.l2LanId = l2LanId;
    }

    /**
     * Returns ID length.
     *
     * @return ID length
     */
    public int getIdLength() {

        return ((idLength == 0) ? 6 : idLength);
    }

    /**
     * Sets ID length.
     *
     * @param idLength ID length
     */
    public void setIdLength(int idLength) {
        this.idLength = idLength;
    }

    /**
     * Returns max area addresses.
     *
     * @return max area addresses
     */
    public int getMaxAreaAddresses() {

        return maxAreaAddresses;
    }

    /**
     * Sets area max addresses.
     *
     * @param maxAreaAddresses max area addresses
     */
    public void setMaxAreaAddresses(int maxAreaAddresses) {
        this.maxAreaAddresses = maxAreaAddresses;
    }

    /**
     * Returns reserved packet circuit type.
     *
     * @return reserved packet circuit type
     */
    public int reservedPacketCircuitType() {
        return reservedPacketCircuitType;
    }

    /**
     * Sets reserved packet circuit type.
     *
     * @param reservedPacketCircuitType reserved packet circuit type
     */
    public void setReservedPacketCircuitType(int reservedPacketCircuitType) {
        this.reservedPacketCircuitType = reservedPacketCircuitType;
    }

    /**
     * Returns point to point.
     *
     * @return point to point
     */
    public IsisNetworkType networkType() {
        return networkType;
    }

    /**
     * Sets point to point or broadcast.
     *
     * @param networkType point to point or broadcast
     */
    public void setNetworkType(IsisNetworkType networkType) {
        this.networkType = networkType;
    }

    /**
     * Returns area address.
     *
     * @return area address
     */
    public String areaAddress() {
        return areaAddress;
    }

    /**
     * Sets area address.
     *
     * @param areaAddress area address
     */
    public void setAreaAddress(String areaAddress) {
        this.areaAddress = areaAddress;
    }

    /**
     * Returns area length.
     *
     * @return area length
     */
    public int getAreaLength() {
        return areaLength;
    }

    /**
     * Sets area length.
     *
     * @param areaLength area length
     */
    public void setAreaLength(int areaLength) {
        this.areaLength = areaLength;
    }

    /**
     * Returns LSP ID.
     *
     * @return LSP ID
     */
    public String getLspId() {
        return lspId;
    }

    /**
     * Sets LSP ID.
     *
     * @param lspId link state packet ID
     */
    public void setLspId(String lspId) {
        this.lspId = lspId;
    }

    /**
     * Returns holding time.
     *
     * @return holding time
     */
    public int holdingTime() {
        return holdingTime;
    }

    /**
     * Sets holding time.
     *
     * @param holdingTime holding time
     */
    public void setHoldingTime(int holdingTime) {
        this.holdingTime = holdingTime;
    }

    /**
     * Returns priority.
     *
     * @return priority
     */
    public int priority() {
        return priority;
    }

    /**
     * Sets priority.
     *
     * @param priority priority
     */
    public void setPriority(int priority) {
        this.priority = priority;
    }

    /**
     * Returns hello interval.
     *
     * @return hello interval
     */
    public int helloInterval() {
        return helloInterval;
    }

    /**
     * Sets hello interval.
     *
     * @param helloInterval hello interval
     */
    public void setHelloInterval(int helloInterval) {
        this.helloInterval = helloInterval;
    }

    /**
     * Returns the interface state.
     *
     * @return interface state
     */
    public IsisInterfaceState interfaceState() {
        return interfaceState;
    }

    /**
     * Sets the interface state.
     *
     * @param interfaceState the interface state
     */
    public void setInterfaceState(IsisInterfaceState interfaceState) {
        this.interfaceState = interfaceState;
    }

    /**
     * Returns the circuit ID.
     *
     * @return circuit ID
     */
    public String circuitId() {
        return circuitId;
    }

    /**
     * Sets the circuit ID.
     *
     * @param circuitId circuit ID
     */
    public void setCircuitId(String circuitId) {
        this.circuitId = circuitId;
    }

    /**
     * Processes received ISIS message.
     * When an ISIS message received it is handed over to this method.
     * Based on the type of the ISIS message received it will be handed over
     * to corresponding message handler methods.
     *
     * @param isisMessage received ISIS message
     * @param isisLsdb    ISIS LSDB instance
     */
    public void processIsisMessage(IsisMessage isisMessage, IsisLsdb isisLsdb, Channel channel) {
        log.debug("IsisInterfaceImpl::processIsisMessage...!!!");
        if (channel == null) {
            this.channel = channel;
        }
        if (this.isisLsdb == null) {
            this.isisLsdb = isisLsdb;
        }

        switch (isisMessage.isisPduType()) {
            case L1HELLOPDU:
            case L2HELLOPDU:
                processL1L2HelloPduMessage(isisMessage, channel);
                break;
            case P2PHELLOPDU:
                processP2pHelloPduMessage(isisMessage, channel);
                break;
            case L1LSPDU:
            case L2LSPDU:
                processLsPduMessage(isisMessage, channel);
                break;
            case L1CSNP:
            case L2CSNP:
                processCsnPduMessage(isisMessage, channel);
                break;
            case L1PSNP:
            case L2PSNP:
                log.debug("Received a PSNP packet...!!!");
                break;
            default:
                log.debug("Unknown packet to process...!!!");
                break;
        }
    }

    /**
     * Validates the received message.
     *
     * @param helloPdu ISIS message instance
     * @return true if valid ISIS message else false
     */
    public boolean validateHelloMessage(HelloPdu helloPdu) {
        boolean isValid = false;

        //Local InterfaceAddress TLV and compare with the IP Interface address and check if they are in same subnet
        List<Ip4Address> interfaceIpAddresses = helloPdu.interfaceIpAddresses();
        Ip4Address neighborIp = (helloPdu.interfaceIpAddresses() != null) ?
                interfaceIpAddresses.get(0) : Ip4Address.valueOf("0.0.0.0");
        if (!IsisUtil.sameNetwork(interfaceIpAddress, neighborIp, networkMask)) {
            return false;
        }

        //Verify if it's in same area, Areas which the router belongs to
        List<String> areas = helloPdu.areaAddress();
        for (String area : areas) {
            if (areaAddress.equals(area)) {
                isValid = true;
            }
        }

        return isValid;
    }

    /**
     * Checks neighbor presents in the list or not.
     *
     * @param neighborMac neighbor MAc address
     * @return true if neighbor exist else false
     */
    private boolean isNeighborInList(MacAddress neighborMac) {
        return neighborList.containsKey(neighborMac);
    }

    /**
     * Adds neighbor in the list.
     *
     * @param neighbor neighbor MAC address
     * @return true if neighbor exist else false
     */
    private void addNeighbouringRouter(IsisNeighbor neighbor) {
        neighborList.put(neighbor.neighborMacAddress(), neighbor);
    }

    /**
     * Returns neighbor presents in the list.
     *
     * @param neighborMac neighbor MAc address
     * @return neighbor instance
     */
    private IsisNeighbor neighbouringRouter(MacAddress neighborMac) {
        return neighborList.get(neighborMac);
    }

    /**
     * Processes the L1 or L2 hello message.
     *
     * @param isisMessage hello message instance
     * @param channel     channel instance
     */
    public void processL1L2HelloPduMessage(IsisMessage isisMessage, Channel channel) {
        log.debug("Enters processL1L2HelloPduMessage ...!!!");
        log.debug("IsisInterfaceImpl::processHelloMessage...!!!");

        L1L2HelloPdu helloPacket = (L1L2HelloPdu) isisMessage;
        log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} ISISInterfaceState {} ",
                  networkType, interfaceState);

        //If L1 Hello, validate the area, network and max address
        if (IsisPduType.get(helloPacket.pduType()) == IsisPduType.L1HELLOPDU &&
                !validateHelloMessage(helloPacket)) {
            return;
        }

        //Get the neighbor
        IsisNeighbor neighbor = neighbouringRouter(isisMessage.sourceMac());
        //Neighbor is not in list
        if (!isNeighborInList(isisMessage.sourceMac())) {
            neighbor = new DefaultIsisNeighbor(helloPacket, this);
            addNeighbouringRouter(neighbor);
        }

        neighbor.stopInactivityTimeCheck();
        neighbor.startInactivityTimeCheck();

        //Assign the DIS
        String lanId = helloPacket.lanId();

        if (IsisPduType.L1HELLOPDU == helloPacket.isisPduType()) {
            buildUpdateAndSendSelfGeneratedLspIfDisChange(l1LanId, lanId, channel);
            l1LanId = lanId;
            neighbor.setL1LanId(lanId);
            //if a change in lanid
        } else if (IsisPduType.L2HELLOPDU == helloPacket.isisPduType()) {
            buildUpdateAndSendSelfGeneratedLspIfDisChange(l1LanId, lanId, channel);
            l2LanId = lanId;
            neighbor.setL2LanId(lanId);
        }

        //Check in neighbors list our MAC address present
        List<MacAddress> neighbors = helloPacket.neighborList();
        for (MacAddress macAddress : neighbors) {
            if (interfaceMacAddress.equals(macAddress)) {
                neighbor.setNeighborState(IsisInterfaceState.UP);
                //Build Self LSP add in LSDB and sent it.
                buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel);
                break;
            }
        }
    }

    /**
     * Builds and store and send self generated LSP.
     *
     * @param channel netty channel instance
     */
    private void buildStoreAndSendSelfGeneratedLspIfNotExistInDb(Channel channel) {
        //Check our LSP is present in DB. else create a self LSP and store it and sent it
        String lspKey = isisLsdb.lspKey(systemId);
        LspWrapper wrapper = null;
        if (reservedPacketCircuitType == IsisRouterType.L1.value()) {
            wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
            if (wrapper == null) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            }
        } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) {
            wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
            if (wrapper == null) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            }
        } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) {
            wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
            if (wrapper == null) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            }

            wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
            if (wrapper == null) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            }
        }
    }

    /**
     * Builds and update in DB and send self generated LSP.
     *
     * @param previousLanId previous DIS ID
     * @param latestLanId   latest DIS ID
     * @param channel       netty channel instance
     */
    private void buildUpdateAndSendSelfGeneratedLspIfDisChange(String previousLanId,
                                                               String latestLanId, Channel channel) {
        //If DIS change then build and sent LSP
        if (previousLanId != null && !previousLanId.equals(IsisConstants.DEFAULTLANID) &&
                !previousLanId.equals(latestLanId)) {
            //Create a self LSP and Update it in DB and sent it
            String lspKey = isisLsdb.lspKey(systemId);
            if (reservedPacketCircuitType == IsisRouterType.L1.value()) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) {
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            } else if (reservedPacketCircuitType == IsisRouterType.L1L2.value()) {
                //L1 LSPDU
                LsPdu lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L1LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
                //L1 LSPDU
                lsp = new LspGenerator().getLsp(this, lspKey, IsisPduType.L2LSPDU, allConfiguredInterfaceIps);
                isisLsdb.addLsp(lsp, true, this);
                sendLsp(lsp, channel);
            }
        }

    }

    /**
     * Sends LS PDU message to channel.
     *
     * @param lsp     LS PDU message instance
     * @param channel channel instance
     */
    private void sendLsp(LsPdu lsp, Channel channel) {
        byte[] lspBytes = lsp.asBytes();
        lspBytes = IsisUtil.addLengthAndMarkItInReserved(lspBytes, IsisConstants.LENGTHPOSITION,
                                                         IsisConstants.LENGTHPOSITION + 1,
                                                         IsisConstants.RESERVEDPOSITION);
        lspBytes = IsisUtil.addChecksum(lspBytes, IsisConstants.CHECKSUMPOSITION,
                                        IsisConstants.CHECKSUMPOSITION + 1);
        //write to the channel
        channel.write(IsisUtil.framePacket(lspBytes, interfaceIndex));
    }

    /**
     * Processes P2P hello message.
     *
     * @param isisMessage hello message instance
     * @param channel     channel instance
     */
    public void processP2pHelloPduMessage(IsisMessage isisMessage, Channel channel) {
        log.debug("Enters processP2pHelloPduMessage ...!!!");
        P2PHelloPdu helloPacket = (P2PHelloPdu) isisMessage;

        log.debug("IsisInterfaceImpl::processHelloMessage::Interface Type {} OSPFInterfaceState {} ",
                  networkType, interfaceState);

        //validate the area, network and max address
        if (!validateHelloMessage(helloPacket)) {
            return;
        }

        IsisNeighbor neighbor = null;
        List<IsisTlv> tlvs = ((P2PHelloPdu) isisMessage).tlvs();
        AdjacencyStateTlv stateTlv = null;
        for (IsisTlv tlv : tlvs) {
            if (tlv instanceof AdjacencyStateTlv) {
                stateTlv = (AdjacencyStateTlv) tlv;
                break;
            }
        }

        if (stateTlv == null) {
            neighbor = neighbouringRouter(isisMessage.sourceMac());
            if (neighbor == null) {
                neighbor = new DefaultIsisNeighbor(helloPacket, this);
                addNeighbouringRouter(neighbor);
            }
            neighbor.setNeighborState(IsisInterfaceState.DOWN);
            buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel);
        } else if (stateTlv.adjacencyType() == IsisInterfaceState.DOWN.value()) {
            neighbor = neighbouringRouter(isisMessage.sourceMac());
            if (neighbor == null) {
                neighbor = new DefaultIsisNeighbor(helloPacket, this);
                addNeighbouringRouter(neighbor);
            }
            neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
        } else if (stateTlv.adjacencyType() == IsisInterfaceState.INITIAL.value()) {
            //Neighbor already present in the list
            neighbor = neighbouringRouter(isisMessage.sourceMac());
            neighbor.setNeighborState(IsisInterfaceState.INITIAL);
            neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
            //interfaceState = IsisInterfaceState.UP;
        } else if (stateTlv.adjacencyType() == IsisInterfaceState.UP.value()) {
            //Build Self LSP add in LSDB and sent it.
            neighbor = neighbouringRouter(isisMessage.sourceMac());
            neighbor.setNeighborState(IsisInterfaceState.UP);
            neighbor.setLocalExtendedCircuitId(stateTlv.localCircuitId());
            buildStoreAndSendSelfGeneratedLspIfNotExistInDb(channel);
        }

        neighbor.stopInactivityTimeCheck();
        neighbor.startInactivityTimeCheck();
    }

    /**
     * Processes LS PDU message.
     *
     * @param isisMessage LS pdu message instance
     * @param channel     channel instance
     */
    public void processLsPduMessage(IsisMessage isisMessage, Channel channel) {
        log.debug("Enters processLsPduMessage ...!!!");
        LsPdu lsPdu = (LsPdu) isisMessage;
        LspWrapper wrapper = isisLsdb.findLsp(lsPdu.isisPduType(), lsPdu.lspId());
        if (wrapper == null || isisLsdb.isNewerOrSameLsp(lsPdu, wrapper.lsPdu()).equalsIgnoreCase("latest")) {
            //not exist in the database or latest, then add it in database
            isisLsdb.addLsp(lsPdu, false, this);
        }

        //If network type is P2P, acknowledge with a PSNP
        if (networkType() == IsisNetworkType.P2P) {
            IsisPduType psnpType = null;
            if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L1LSPDU) {
                psnpType = IsisPduType.L1PSNP;
            } else if (IsisPduType.get(lsPdu.pduType()) == IsisPduType.L2LSPDU) {
                psnpType = IsisPduType.L2PSNP;
            }
            IsisHeader isisHeader = new LspGenerator().getHeader(psnpType);
            Psnp psnp = new Psnp(isisHeader);
            psnp.setSourceId(lspKeyP2P(this.systemId));
            TlvHeader tlvHeader = new TlvHeader();
            tlvHeader.setTlvType(TlvType.LSPENTRY.value());
            tlvHeader.setTlvLength(0);
            LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader);
            LspEntry lspEntry = new LspEntry();
            lspEntry.setLspChecksum(lsPdu.checkSum());
            lspEntry.setLspId(lsPdu.lspId());
            lspEntry.setLspSequenceNumber(lsPdu.sequenceNumber());
            lspEntry.setRemainingTime(lsPdu.remainingLifeTime());
            lspEntriesTlv.addLspEntry(lspEntry);
            psnp.addTlv(lspEntriesTlv);

            //write it to channel buffer.
            byte[] psnpBytes = psnp.asBytes();
            psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION,
                                                              IsisConstants.LENGTHPOSITION + 1,
                                                              IsisConstants.RESERVEDPOSITION);
            flagValue = false;
            //write to the channel
            channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex));
        }
    }

    /**
     * Processes CSN PDU message.
     *
     * @param isisMessage CSN PDU message instance
     * @param channel     channel instance
     */
    public void processCsnPduMessage(IsisMessage isisMessage, Channel channel) {
        log.debug("Enters processCsnPduMessage ...!!!");
        if (reservedPacketCircuitType == IsisRouterType.L1.value()) {
            processOnL1CsnPdu(isisMessage, channel);
        } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) {
            processOnL2CsnPdu(isisMessage, channel);
        }
    }

    /**
     * Process the isisMessage which belongs to L1 CSN PDU.
     * checks the database for this LsPdu if it exists further check for sequence number
     * sequence number is greater will send PsnPdu.
     *
     * @param isisMessage CSN PDU message instance
     * @param channel     netty channel instance
     */
    private void processOnL1CsnPdu(IsisMessage isisMessage, Channel channel) {
        Csnp csnPacket = (Csnp) isisMessage;
        List<LspEntry> lspEntryRequestList = new ArrayList<>();
        boolean selfOriginatedFound = false;
        if (IsisPduType.L1CSNP.equals(csnPacket.isisPduType())) {
            List<IsisTlv> isisTlvs = csnPacket.getAllTlv();
            Iterator iterator = isisTlvs.iterator();
            while (iterator.hasNext()) {
                IsisTlv isisTlv = (IsisTlv) iterator.next();
                if (isisTlv instanceof LspEntriesTlv) {
                    LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv;
                    List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry();
                    Iterator lspEntryListIterator = lspEntryList.iterator();
                    while (lspEntryListIterator.hasNext()) {
                        LspEntry lspEntry = (LspEntry) lspEntryListIterator.next();
                        String lspKey = lspEntry.lspId();
                        LspWrapper lspWrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
                        if (lspWrapper != null) {
                            LsPdu lsPdu = (LsPdu) lspWrapper.lsPdu();
                            if (lspWrapper.isSelfOriginated()) {
                                selfOriginatedFound = true;
                                if (lspEntry.lspSequenceNumber() > lsPdu.sequenceNumber()) {
                                    sendLsPduMessage(lspEntry.lspSequenceNumber(), csnPacket.isisPduType(), channel);
                                }
                            } else {
                                if (lsPdu.sequenceNumber() < lspEntry.lspSequenceNumber()) {
                                    lspEntryRequestList.add(lspEntry);
                                    flagValue = true;
                                }
                            }
                        } else {
                            lspEntryRequestList.add(lspEntry);
                            flagValue = true;
                        }
                    }
                }
            }
            if (flagValue) {
                sendPsnPduMessage(lspEntryRequestList, csnPacket.isisPduType(), channel);
            }

            if (!selfOriginatedFound) {
                String lspKey = isisLsdb.lspKey(systemId);
                LspWrapper wrapper = isisLsdb.findLsp(IsisPduType.L1LSPDU, lspKey);
                sendLsp((LsPdu) wrapper.lsPdu(), channel);
            }
        }
    }

    /**
     * Process the isisMessage which belongs to L2 CSNP.
     * checks the database for this LsPdu if it exists further check for sequence number
     * sequence number is greater will send PsnPdu.
     *
     * @param isisMessage received CSNP message
     * @param channel     netty channel instance
     */
    private void processOnL2CsnPdu(IsisMessage isisMessage, Channel channel) {
        Csnp csnPacket = (Csnp) isisMessage;
        List<LspEntry> lspEntryRequestList = new ArrayList<>();
        boolean selfOriginatedFound = false;
        if (IsisPduType.L2CSNP.equals(csnPacket.isisPduType())) {
            List<IsisTlv> isisTlvs = csnPacket.getAllTlv();
            Iterator iterator = isisTlvs.iterator();
            while (iterator.hasNext()) {
                IsisTlv isisTlv = (IsisTlv) iterator.next();
                if (isisTlv instanceof LspEntriesTlv) {
                    LspEntriesTlv lspEntriesTlv = (LspEntriesTlv) isisTlv;
                    List<LspEntry> lspEntryList = lspEntriesTlv.lspEntry();
                    Iterator lspEntryListIterator = lspEntryList.iterator();
                    while (lspEntryListIterator.hasNext()) {
                        LspEntry lspEntry = (LspEntry) lspEntryListIterator.next();
                        String lspKey = lspEntry.lspId();
                        LspWrapper lspWrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
                        if (lspWrapper != null) {
                            LsPdu lsPdu = (LsPdu) lspWrapper.lsPdu();
                            if (lspWrapper.isSelfOriginated()) {
                                selfOriginatedFound = true;
                                if (lspEntry.lspSequenceNumber() > lsPdu.sequenceNumber()) {
                                    sendLsPduMessage(lspEntry.lspSequenceNumber(), csnPacket.isisPduType(), channel);
                                }
                            } else {
                                if (lsPdu.sequenceNumber() < lspEntry.lspSequenceNumber()) {
                                    lspEntryRequestList.add(lspEntry);
                                    flagValue = true;
                                }
                            }
                        } else {
                            lspEntryRequestList.add(lspEntry);
                            flagValue = true;
                        }
                    }
                }
            }
            if (flagValue) {
                sendPsnPduMessage(lspEntryRequestList, csnPacket.isisPduType(), channel);
                lspEntryRequestList.clear();
            }

            if (!selfOriginatedFound) {
                String lspKey = isisLsdb.lspKey(systemId);
                LspWrapper wrapper = isisLsdb.findLsp(IsisPduType.L2LSPDU, lspKey);
                sendLsp((LsPdu) wrapper.lsPdu(), channel);
            }
        }
    }

    /**
     * Sends the partial sequence number PDU.
     *
     * @param lspEntryRequestList list of lsp entry request
     * @param isisPduType         intermediate system PDU type
     * @param channel             netty channel instance
     */
    private void sendPsnPduMessage(List<LspEntry> lspEntryRequestList, IsisPduType isisPduType, Channel channel) {
        IsisPduType psnpType = null;
        if (isisPduType == IsisPduType.L1CSNP) {
            psnpType = IsisPduType.L1PSNP;
        } else if (reservedPacketCircuitType == IsisRouterType.L2.value()) {
            psnpType = IsisPduType.L2PSNP;
        }
        IsisHeader isisHeader = new LspGenerator().getHeader(psnpType);
        Psnp psnp = new Psnp(isisHeader);
        psnp.setSourceId(lspKeyP2P(this.systemId));
        TlvHeader tlvHeader = new TlvHeader();
        tlvHeader.setTlvType(TlvType.LSPENTRY.value());
        tlvHeader.setTlvLength(0);
        LspEntriesTlv lspEntriesTlv = new LspEntriesTlv(tlvHeader);
        for (LspEntry lspEntry : lspEntryRequestList) {
            lspEntriesTlv.addLspEntry(lspEntry);
        }
        psnp.addTlv(lspEntriesTlv);
        //write it to channel buffer.
        byte[] psnpBytes = psnp.asBytes();
        psnpBytes = IsisUtil.addLengthAndMarkItInReserved(psnpBytes, IsisConstants.LENGTHPOSITION,
                                                          IsisConstants.LENGTHPOSITION + 1,
                                                          IsisConstants.RESERVEDPOSITION);
        flagValue = false;
        //write to the channel
        channel.write(IsisUtil.framePacket(psnpBytes, interfaceIndex));
    }

    /**
     * Gets the LSP key.
     *
     * @param systemId system ID
     * @return key
     */
    public String lspKeyP2P(String systemId) {
        StringBuilder lspKey = new StringBuilder();
        lspKey.append(systemId);
        lspKey.append(".00");
        return lspKey.toString();
    }

    /**
     * Sends the link state PDU with latest self generated lsp entry.
     *
     * @param sequenceNumber sequence number of the self generated lsp
     * @param isisPduType    intermediate system type
     * @param channel        netty channel instance
     */
    private void sendLsPduMessage(int sequenceNumber, IsisPduType isisPduType, Channel channel) {
        String lspKey = isisLsdb.lspKey(systemId);
        LsPdu lsp = new LspGenerator().getLsp(this, lspKey, isisPduType, allConfiguredInterfaceIps);
        lsp.setSequenceNumber(sequenceNumber);
        byte[] lspBytes = lsp.asBytes();
        lspBytes = IsisUtil.addLengthAndMarkItInReserved(lspBytes, IsisConstants.LENGTHPOSITION,
                                                         IsisConstants.LENGTHPOSITION + 1,
                                                         IsisConstants.RESERVEDPOSITION);
        lspBytes = IsisUtil.addChecksum(lspBytes, IsisConstants.CHECKSUMPOSITION,
                                        IsisConstants.CHECKSUMPOSITION + 1);
        //write to the channel
        channel.write(IsisUtil.framePacket(lspBytes, interfaceIndex));
    }


    /**
     * Starts the hello timer which sends hello packet every configured seconds.
     *
     * @param channel netty channel instance
     */
    public void startHelloSender(Channel channel) {
        log.debug("IsisInterfaceImpl::startHelloSender");

        isisHelloPduSender = new IsisHelloPduSender(channel, this);
        exServiceHello = Executors.newSingleThreadScheduledExecutor();
        final ScheduledFuture<?> helloHandle =
                exServiceHello.scheduleAtFixedRate(isisHelloPduSender, 0,
                                                   helloInterval, TimeUnit.SECONDS);
    }
}