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

import org.onlab.util.Bandwidth;
import org.onosproject.isis.controller.topology.DeviceInformation;
import org.onosproject.isis.controller.topology.IsisRouter;
import org.onosproject.isis.controller.topology.LinkInformation;
import org.onosproject.isis.controller.topology.TopologyForDeviceAndLink;
import org.onosproject.isis.controller.topology.IsisLinkTed;
import org.onosproject.isis.io.isispacket.pdu.LsPdu;
import org.onosproject.isis.io.isispacket.tlv.IsExtendedReachability;
import org.onosproject.isis.io.isispacket.tlv.IsisTlv;
import org.onosproject.isis.io.isispacket.tlv.NeighborForExtendedIs;

import org.onosproject.isis.io.isispacket.tlv.subtlv.TrafficEngineeringSubTlv;
import org.onosproject.isis.io.isispacket.tlv.subtlv.InterfaceIpAddress;
import org.onosproject.isis.io.isispacket.tlv.subtlv.NeighborIpAddress;
import org.onosproject.isis.io.isispacket.tlv.subtlv.AdministrativeGroup;
import org.onosproject.isis.io.isispacket.tlv.subtlv.TrafficEngineeringMetric;
import org.onosproject.isis.io.isispacket.tlv.subtlv.UnreservedBandwidth;
import org.onosproject.isis.io.isispacket.tlv.subtlv.MaximumReservableBandwidth;
import org.onosproject.isis.io.isispacket.tlv.subtlv.MaximumBandwidth;
import org.onosproject.isis.io.util.IsisConstants;
import org.onosproject.isis.io.util.IsisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Represents device and link topology information.
 */
public class TopologyForDeviceAndLinkImpl implements TopologyForDeviceAndLink {

    private static final Logger log = LoggerFactory.getLogger(TopologyForDeviceAndLinkImpl.class);
    private Map<String, DeviceInformation> deviceInformationMap = new LinkedHashMap<>();
    private Map<String, IsisRouter> isisRouterDetails = new LinkedHashMap<>();
    private Map<String, DeviceInformation> deviceInformationMapForPointToPoint = new LinkedHashMap<>();
    private Map<String, DeviceInformation> deviceInformationMapToDelete = new LinkedHashMap<>();
    private Map<String, LinkInformation> addedLinkInformationMap = new LinkedHashMap<>();

    /**
     * Gets device information.
     *
     * @return device information
     */
    public Map<String, DeviceInformation> deviceInformationMap() {
        return deviceInformationMap;
    }

    /**
     * Gets ISIS router list information.
     *
     * @return router information
     */
    public Map<String, IsisRouter> isisDeviceList() {
        return isisRouterDetails;
    }

    /**
     * Sets device information.
     *
     * @param key                  key used to add in map
     * @param deviceInformationMap device information instance
     */
    public void setDeviceInformationMap(String key, DeviceInformation deviceInformationMap) {
        if (deviceInformationMap != null) {
            this.deviceInformationMap.put(key, deviceInformationMap);
        }

    }

    /**
     * Gets deviceInformation as map for Point-To-Point.
     *
     * @return deviceInformationMap
     */
    public Map<String, DeviceInformation> deviceInformationMapForPointToPoint() {
        return deviceInformationMapForPointToPoint;
    }

    /**
     * Sets deviceInformation as map for Point-To-Point..
     *
     * @param key                  key used to add in map
     * @param deviceInformationMap device information instance
     */
    public void setDeviceInformationMapForPointToPoint(String key, DeviceInformation deviceInformationMap) {
        if (deviceInformationMap != null) {
            this.deviceInformationMapForPointToPoint.put(key, deviceInformationMap);
        }

    }

    /**
     * Gets deviceInformation as map.
     *
     * @return deviceInformationMap to delete from core
     */
    public Map<String, DeviceInformation> deviceInformationMapToDelete() {
        return deviceInformationMapToDelete;
    }

    /**
     * Sets device information for removal.
     *
     * @param key                          ket used to add in map
     * @param deviceInformationMapToDelete map from device information to remove
     */
    public void setDeviceInformationMapToDelete(String key, DeviceInformation deviceInformationMapToDelete) {
        if (deviceInformationMapToDelete != null) {
            this.deviceInformationMapToDelete.put(key, deviceInformationMapToDelete);
        }
    }

    /**
     * Removes Device Information.
     *
     * @param key ket used to remove from map
     */
    public void removeDeviceInformationMapFromDeleteMap(String key) {
        removeDeviceInformationMap(key);
        if (this.deviceInformationMapToDelete.containsKey(key)) {
            this.deviceInformationMapToDelete.remove(key);
        }
    }

    /**
     * Gets Device Information.
     *
     * @param key system id as key to store in map
     * @return Device Information
     */
    public DeviceInformation deviceInformation(String key) {
        DeviceInformation deviceInformation = this.deviceInformationMap.get(key);
        return deviceInformation;
    }

    /**
     * Removes Device Information from map.
     *
     * @param key key used to remove from map
     */
    public void removeDeviceInformationMap(String key) {
        if (this.deviceInformationMap.containsKey(key)) {
            this.deviceInformationMap.remove(key);
        }
    }

    @Override
    public void removeLinks(String linkId) {
        this.addedLinkInformationMap.remove(linkId);
    }

    /**
     * Gets link information as map.
     *
     * @return link information as map
     */
    public Map<String, LinkInformation> linkInformationMap() {
        return addedLinkInformationMap;
    }

    private LinkInformation getLinkInformation(String key) {
        LinkInformation linkInformation = this.addedLinkInformationMap.get(key);
        return linkInformation;
    }

    /**
     * Sets link information in map.
     *
     * @param key                key used to add in map
     * @param linkInformationMap link information instance
     */
    public void setLinkInformationMap(String key, LinkInformation linkInformationMap) {
        if (!this.addedLinkInformationMap.containsKey(key)) {
            this.addedLinkInformationMap.put(key, linkInformationMap);
        }
    }

    /**
     * Gets linkInformation as map for PointToPoint.
     *
     * @return linkInformationMap
     */
    public Map<String, LinkInformation> linkInformationMapForPointToPoint() {
        return addedLinkInformationMap;
    }

    /**
     * Sets linkInformation as map for PointToPoint.
     *
     * @param key                key used to add in map
     * @param linkInformationMap link information instance
     */
    public void setLinkInformationMapForPointToPoint(String key, LinkInformation linkInformationMap) {
        if (!this.addedLinkInformationMap.containsKey(key)) {
            this.addedLinkInformationMap.put(key, linkInformationMap);
        }
    }

    /**
     * Removes Link Information from linkInformationMap.
     *
     * @param key key used to remove in map
     */
    public void removeLinkInformationMap(String key) {
        if (this.addedLinkInformationMap.containsKey(key)) {
            this.addedLinkInformationMap.remove(key);
        }
    }

    /**
     * Returns the ISIS router instance.
     *
     * @param systemId system ID to get router details
     * @return ISIS router instance
     */
    public IsisRouter isisRouter(String systemId) {
        String routerId = IsisUtil.removeTailingZeros(systemId);
        IsisRouter isisRouter = isisRouterDetails.get(routerId);
        if (isisRouter != null) {
            return isisRouter;
        } else {
            log.debug("IsisRouter is not available");
            IsisRouter isisRouterCheck = new DefaultIsisRouter();
            isisRouterCheck.setSystemId(routerId);
            return isisRouterCheck;
        }
    }

    /**
     * Removes the ISIS router instance from map.
     *
     * @param systemId system ID to remove router details
     */
    public void removeRouter(String systemId) {
        String routerId = IsisUtil.removeTailingZeros(systemId);
        isisRouterDetails.remove(systemId);
    }

    /**
     * Creates Device instance.
     *
     * @param lsPdu ISIS LSPDU instance
     * @return isisRouter isisRouter instance
     */
    public IsisRouter createDeviceInfo(LsPdu lsPdu) {
        IsisRouter isisRouter = createIsisRouter(lsPdu);

        if (isisRouter.systemId() != null) {
            if (isisRouter.interfaceId() == null && isisRouter.neighborRouterId() == null) {
                isisRouter.setInterfaceId(IsisConstants.DEFAULTIP);
                isisRouter.setNeighborRouterId(IsisConstants.DEFAULTIP);
                isisRouterDetails.put(isisRouter.systemId(), isisRouter);
            }
        }
        return isisRouter;
    }/*

    *//**
     * Removes Device and Link instance.
     *
     * @param lsPdu ISIS LSPDU instance
     * @return isisRouter isisRouter instance
     *//*
    public IsisRouter removeDeviceAndLinkInfo(LsPdu lsPdu) {
        IsisRouter isisRouter = createIsisRouter(lsPdu);
        return isisRouter;
    }*/

    /**
     * Creates link information.
     *
     * @param lsPdu       ls pdu instance
     * @param ownSystemId system ID
     * @return link information
     */
    public Map<String, LinkInformation> createLinkInfo(LsPdu lsPdu, String ownSystemId) {
        for (IsisTlv isisTlv : lsPdu.tlvs()) {
            if (isisTlv instanceof IsExtendedReachability) {
                IsExtendedReachability isExtendedReachability = (IsExtendedReachability) isisTlv;
                List<NeighborForExtendedIs> neighborForExtendedIsList = isExtendedReachability.neighbours();
                for (NeighborForExtendedIs neighbor : neighborForExtendedIsList) {
                    String neighbourId = neighbor.neighborId();
                    String routerId = IsisUtil.removeTailingZeros(lsPdu.lspId());
                    if (!(neighbourId.equals(ownSystemId))) {
                        IsisRouter isisRouter = isisRouterDetails.get(neighbourId);
                        if (isisRouter != null) {
                            String linkId = "link:" + routerId + "-" + neighbourId;
                            addedLinkInformationMap.put(linkId, createLinkInformation(lsPdu, linkId,
                                    routerId, neighbourId));
                        } else {
                            createIsisRouterDummy(neighbourId);
                            String linkId = "link:" + routerId + "-" + neighbourId;
                            LinkInformation linkInformation = createLinkInformation(lsPdu, linkId,
                                    routerId, neighbourId);
                            linkInformation.setAlreadyCreated(true);
                            addedLinkInformationMap.put(linkId, linkInformation);
                        }
                    }

                }
            }
        }
        return addedLinkInformationMap;
    }

    /**
     * Removes link information.
     *
     * @param systemId system ID to remove link information
     * @return updated link information
     */
    public Map<String, LinkInformation> removeLinkInfo(String systemId) {
        String routerId = IsisUtil.removeTailingZeros(systemId);
        Map<String, LinkInformation> removeLinkInformationMap = new LinkedHashMap<>();
        for (String key : addedLinkInformationMap.keySet()) {
            if (key.contains(routerId)) {
                removeLinkInformationMap.put(key, addedLinkInformationMap.get(key));
            }
        }
        return removeLinkInformationMap;
    }

    /**
     * Creates link information.
     *
     * @param lsPdu       link state pdu
     * @param linkId      link id
     * @param localRouter local router system id
     * @param neighborId  destination router system id
     * @return linkInformation instance
     */
    private LinkInformation createLinkInformation(LsPdu lsPdu, String linkId, String localRouter, String neighborId) {
        LinkInformation linkInformation = new DefaultIsisLinkInformation();
        IsisRouter isisRouter = isisRouterDetails.get(neighborId);
        for (IsisTlv isisTlv : lsPdu.tlvs()) {
            if (isisTlv instanceof IsExtendedReachability) {
                IsExtendedReachability isExtendedReachability = (IsExtendedReachability) isisTlv;
                List<NeighborForExtendedIs> neighbours = isExtendedReachability.neighbours();
                for (NeighborForExtendedIs teTlv : neighbours) {
                    List<TrafficEngineeringSubTlv> teSubTlvs = teTlv.teSubTlv();
                    for (TrafficEngineeringSubTlv teSubTlv : teSubTlvs) {
                        if (teSubTlv instanceof InterfaceIpAddress) {
                            InterfaceIpAddress localIpAddress = (InterfaceIpAddress) teSubTlv;
                            linkInformation.setInterfaceIp(localIpAddress.localInterfaceIPAddress());
                        } else if (teSubTlv instanceof NeighborIpAddress) {
                            NeighborIpAddress neighborIpAddress = (NeighborIpAddress) teSubTlv;
                            linkInformation.setNeighborIp(neighborIpAddress.neighborIPAddress());
                        }

                    }
                }
            }
        }
        linkInformation.setLinkId(linkId);
        linkInformation.setAlreadyCreated(false);
        linkInformation.setLinkDestinationId(neighborId);
        linkInformation.setLinkSourceId(localRouter);
        return linkInformation;
    }

    /**
     * Creates ISIS router instance.
     *
     * @param lsPdu lsp instance
     * @return isisRouter instance
     */
    private IsisRouter createIsisRouter(LsPdu lsPdu) {
        IsisRouter isisRouter = new DefaultIsisRouter();
        if (IsisUtil.checkIsDis(lsPdu.lspId())) {
            isisRouter.setDis(true);
        } else {
            isisRouter.setDis(false);
        }
        isisRouter.setSystemId(IsisUtil.removeTailingZeros(lsPdu.lspId()));
        for (IsisTlv isisTlv : lsPdu.tlvs()) {
            if (isisTlv instanceof IsExtendedReachability) {
                IsExtendedReachability isExtendedReachability = (IsExtendedReachability) isisTlv;
                List<NeighborForExtendedIs> neighbours = isExtendedReachability.neighbours();
                for (NeighborForExtendedIs teTlv : neighbours) {
                    List<TrafficEngineeringSubTlv> teSubTlvs = teTlv.teSubTlv();
                    for (TrafficEngineeringSubTlv teSubTlv : teSubTlvs) {
                        if (teSubTlv instanceof InterfaceIpAddress) {
                            InterfaceIpAddress localIpAddress = (InterfaceIpAddress) teSubTlv;
                            isisRouter.setInterfaceId(localIpAddress.localInterfaceIPAddress());
                        } else if (teSubTlv instanceof NeighborIpAddress) {
                            NeighborIpAddress neighborIpAddress = (NeighborIpAddress) teSubTlv;
                            isisRouter.setNeighborRouterId(neighborIpAddress.neighborIPAddress());
                        }

                    }
                }
            }
        }
        return isisRouter;
    }

    /**
     * Creates ISIS router instance.
     *
     * @param systemId system ID
     * @return isisRouter instance
     */
    private IsisRouter createIsisRouterDummy(String systemId) {
        IsisRouter isisRouter = new DefaultIsisRouter();
        isisRouter.setSystemId(systemId);
        isisRouter.setDis(false);
        isisRouter.setInterfaceId(IsisConstants.DEFAULTIP);
        isisRouter.setNeighborRouterId(IsisConstants.DEFAULTIP);

        return isisRouter;
    }

    /**
     * Creates the ISIS link TED information.
     *
     * @param lsPdu link state PDU
     * @return isisLinkTed
     */
    public IsisLinkTed createIsisLinkTedInfo(LsPdu lsPdu) {
        IsisLinkTed isisLinkTed = new DefaultIsisLinkTed();
        for (IsisTlv isisTlv : lsPdu.tlvs()) {
            if (isisTlv instanceof IsExtendedReachability) {
                IsExtendedReachability isExtendedReachability = (IsExtendedReachability) isisTlv;
                List<NeighborForExtendedIs> neighbours = isExtendedReachability.neighbours();
                for (NeighborForExtendedIs teTlv : neighbours) {
                    List<TrafficEngineeringSubTlv> teSubTlvs = teTlv.teSubTlv();
                    for (TrafficEngineeringSubTlv teSubTlv : teSubTlvs) {
                        if (teSubTlv instanceof AdministrativeGroup) {
                            AdministrativeGroup ag = (AdministrativeGroup) teSubTlv;
                            isisLinkTed.setAdministrativeGroup(ag.administrativeGroup());
                        }
                        if (teSubTlv instanceof InterfaceIpAddress) {
                            InterfaceIpAddress localIpAddress = (InterfaceIpAddress) teSubTlv;
                            isisLinkTed.setIpv4InterfaceAddress(localIpAddress.localInterfaceIPAddress());
                        }
                        if (teSubTlv instanceof NeighborIpAddress) {
                            NeighborIpAddress neighborIpAddress = (NeighborIpAddress) teSubTlv;
                            isisLinkTed.setIpv4NeighborAddress(neighborIpAddress.neighborIPAddress());
                        }
                        if (teSubTlv instanceof TrafficEngineeringMetric) {
                            TrafficEngineeringMetric teM = (TrafficEngineeringMetric) teSubTlv;
                            isisLinkTed.setTeDefaultMetric(teM.getTrafficEngineeringMetricValue());
                        }
                        if (teSubTlv instanceof MaximumBandwidth) {
                            MaximumBandwidth maxLinkBandwidth = (MaximumBandwidth) teSubTlv;
                            isisLinkTed.setMaximumLinkBandwidth(
                                    Bandwidth.bps(maxLinkBandwidth.getMaximumBandwidthValue()));
                        }
                        if (teSubTlv instanceof MaximumReservableBandwidth) {
                            MaximumReservableBandwidth maxReservableBw = (MaximumReservableBandwidth) teSubTlv;
                            isisLinkTed.setMaximumReservableLinkBandwidth(
                                    Bandwidth.bps(maxReservableBw.getMaximumBandwidthValue()));
                        }
                        if (teSubTlv instanceof UnreservedBandwidth) {
                            UnreservedBandwidth unReservedBandwidth = (UnreservedBandwidth) teSubTlv;
                            List<Bandwidth> bandwidthList = new ArrayList<>();
                            List<Float> unReservedBandwidthList = unReservedBandwidth.unReservedBandwidthValue();
                            for (Float unReservedBandwidthFloatValue : unReservedBandwidthList) {
                                Bandwidth bandwidth = Bandwidth.bps(unReservedBandwidthFloatValue);
                                bandwidthList.add(bandwidth);
                            }
                            isisLinkTed.setUnreservedBandwidth(bandwidthList);
                        }
                    }
                }
            }
        }
        return isisLinkTed;
    }
}