/*
 * Copyright 2016-present Open Networking Foundation
 *
 * 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.tetopology.management;

import java.util.BitSet;
import java.util.List;
import java.util.Map;

import org.onlab.packet.Ip4Address;
import org.onosproject.net.DeviceId;
import org.onosproject.tetopology.management.api.DefaultNetwork;
import org.onosproject.tetopology.management.api.EncodingType;
import org.onosproject.tetopology.management.api.KeyId;
import org.onosproject.tetopology.management.api.Network;
import org.onosproject.tetopology.management.api.OptimizationType;
import org.onosproject.tetopology.management.api.SwitchingType;
import org.onosproject.tetopology.management.api.TeConstants;
import org.onosproject.tetopology.management.api.TeStatus;
import org.onosproject.tetopology.management.api.TeTopologyId;
import org.onosproject.tetopology.management.api.TeTopologyKey;
import org.onosproject.tetopology.management.api.link.CommonLinkData;
import org.onosproject.tetopology.management.api.link.DefaultNetworkLink;
import org.onosproject.tetopology.management.api.link.DefaultTeLink;
import org.onosproject.tetopology.management.api.link.ExternalLink;
import org.onosproject.tetopology.management.api.link.LinkBandwidth;
import org.onosproject.tetopology.management.api.link.NetworkLink;
import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
import org.onosproject.tetopology.management.api.link.OduResource;
import org.onosproject.tetopology.management.api.link.TeLink;
import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
import org.onosproject.tetopology.management.api.link.TePathAttributes;
import org.onosproject.tetopology.management.api.link.UnderlayPath;
import org.onosproject.tetopology.management.api.node.CommonNodeData;
import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
import org.onosproject.tetopology.management.api.node.DefaultNetworkNode;
import org.onosproject.tetopology.management.api.node.DefaultTeNode;
import org.onosproject.tetopology.management.api.node.DefaultTerminationPoint;
import org.onosproject.tetopology.management.api.node.DefaultTunnelTerminationPoint;
import org.onosproject.tetopology.management.api.node.NetworkNode;
import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
import org.onosproject.tetopology.management.api.node.NodeTpKey;
import org.onosproject.tetopology.management.api.node.TeNode;
import org.onosproject.tetopology.management.api.node.TeNodeKey;
import org.onosproject.tetopology.management.api.node.TerminationPoint;
import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
import org.onosproject.tetopology.management.impl.TeMgrUtil;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Builds a sample abstract TE Topology, which consists of one node(represents
 * an entire network), one inter-domain link and one TTP.
 */
public final class DefaultBuilder {
    private static final String NODEIP = "100.10.10.10";
    // Bandwidth in GigaBits/second
    private static final float[] ODU0BW = {1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f, 1.25f};
    private static final float[] ODU2BW = {10, 10, 10, 10, 10, 10, 10, 10};
    private static final float[] ODU3BW = {40, 40, 40, 40, 40, 40, 40, 40};
    private static final float[] ODU4BW = {100, 100, 100, 100, 100, 100, 100, 100};

    private static final String ODU2 = "ODU2";
    private static final String ODU3 = "ODU3";
    private static final String ODU4 = "ODU4";

    private static final long PROVIDER_ID = 0x100;
    private static final long CLIENT_ID = 0x0a0a0a0a;
    private static final long CLIENT_NIL = 0;
    private static final long ABSTRACT_TOPOLOGY_ID = 100;
    private static final long NATIVE_TOPOLOGY_ID = 1;
    private static final long NUM_TPS = 1;
    private static final long NUM_TTPS = 1;
    private static final boolean ABSTRACT = true;
    private static final boolean UNABSTRACT = false;
    private static final int FIRST_INDEX = 0;
    private static final long INTER_DOMAIN_LINK_PLUGID = 100;
    private static final long LINK_COST = 500;
    private static final long LINK_DELAY = 2000;
    private static final long LINK_SRLG = 150;
    private static final String DOMAIN_ID = "DomainX";

    private static NetworkNode networkNode;
    private static TeNode teNode;
    private static NetworkLink networkLink;
    private static TeLink teLink;
    private static Network network;
    private static TunnelTerminationPoint ttp;

    private static TeTopologyKey teTopologyKey = new TeTopologyKey(PROVIDER_ID,
                                                                   CLIENT_ID,
                                                                   ABSTRACT_TOPOLOGY_ID);

    // no instantiation
    private DefaultBuilder() {
    }

    private static TunnelTerminationPoint ttpBuilder(long ttpId) {
        return new DefaultTunnelTerminationPoint(ttpId, SwitchingType.OTN_TDM_CAPABLE,
                                                 EncodingType.LSP_ENCODING_ODUK,
                                                 new BitSet(TeConstants.FLAG_MAX_BITS),
                                                 null, null,
                                                 ODU2BW, null); //10G for ODU2
    }

    private static TerminationPoint tpBuilder(long teTpId) {
        return new DefaultTerminationPoint(KeyId.keyId(Long.toString(teTpId)), null, teTpId);
    }

    private static NetworkNode nodeBuilder(String nodeIp, long numTps, long numTtps,
                                          TeTopologyKey underlayTopologyId, TeNodeKey supportTeNodeId,
                                          TeNodeKey sourceTeNodeId, boolean isAbstract) {
        long teNodeId = Ip4Address.valueOf(nodeIp).toInt();
        BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);

        if (isAbstract) {
            flags.set(TeNode.BIT_ABSTRACT);
        }
        CommonNodeData common = new CommonNodeData(nodeIp, TeStatus.UP, TeStatus.UP, flags);
        Map<Long, ConnectivityMatrix> connMatrices = null;
        List<Long> teTpIds = Lists.newArrayList();
        Map<KeyId, TerminationPoint> tps = Maps.newHashMap();
        for (long i = 0; i < numTps; i++) {
            teTpIds.add(i);
            tps.put(KeyId.keyId(Long.toString(i)), tpBuilder(i));
        }
        //TTP
        Map<Long, TunnelTerminationPoint> ttps = Maps.newHashMap();
        for (long i = 0; i < numTtps; i++) {
            ttps.put(i, ttpBuilder(i));
        }
        ttp = ttps.get(FIRST_INDEX);
        //TeNode
        teNode = new DefaultTeNode(teNodeId, underlayTopologyId,
                                   supportTeNodeId, sourceTeNodeId,
                                          common, connMatrices, teTpIds, ttps, teTpIds);
        List<NetworkNodeKey> supportingNodeIds = null;
        if (supportTeNodeId != null) {
            supportingNodeIds = Lists
                    .newArrayList(TeMgrUtil.networkNodeKey(supportTeNodeId));
        }

        return new DefaultNetworkNode(KeyId.keyId(nodeIp), supportingNodeIds, teNode, tps);
    }

    private static LinkBandwidth linkBwBuilder(String odu) {

        float[] maxBandwidth;  //Maximum bandwidth, Size is MAX_PRIORITY + 1
        float[] avaiBandwidth; //Unreserved bandwidth, Size is MAX_PRIORITY + 1
        float[] maxAvialLspBandwidth;  //Maximum available bandwidth for a LSP
        float[] minAvialLspBandwidth;  //Minimum available bandwidth for a LSP
        short odu0s;
        short odu1s;
        short odu2s;
        short odu2es = 0;
        short odu3s;
        short odu4s;
        short oduFlexes = 0;

        switch (odu) {
        case ODU3:
            maxBandwidth = ODU3BW;
            avaiBandwidth = ODU3BW;
            maxAvialLspBandwidth = ODU3BW;
            minAvialLspBandwidth = ODU0BW;
            odu0s = 32;
            odu1s = 16;
            odu2s = 4;
            odu3s = 1;
            odu4s = 0;
            break;
        case ODU4:
            maxBandwidth = ODU4BW;
            avaiBandwidth = ODU4BW;
            maxAvialLspBandwidth = ODU4BW;
            minAvialLspBandwidth = ODU0BW;
            odu0s = 80;
            odu1s = 40;
            odu2s = 10;
            odu3s = 2;
            odu4s = 1;
            break;
        default:
            maxBandwidth = ODU2BW;
            avaiBandwidth = ODU2BW;
            maxAvialLspBandwidth = ODU2BW;
            minAvialLspBandwidth = ODU0BW;
            odu0s = 8;
            odu1s = 4;
            odu2s = 1;
            odu3s = 0;
            odu4s = 0;
        }

        OduResource oduRrc = new OduResource(odu0s, odu1s, odu2s, odu2es, odu3s,
                                             odu4s, oduFlexes);
        return new LinkBandwidth(maxBandwidth, avaiBandwidth, maxAvialLspBandwidth,
                                 minAvialLspBandwidth, oduRrc);
    }

    private static NetworkLink linkBuilder(TeLinkTpKey teLinkKey, TeLinkTpKey peerTeLinkKey,
                                          TeTopologyKey underlayTopologyId, TeLinkTpGlobalKey supportTeLinkId,
                                          TeLinkTpGlobalKey sourceTeLinkId, boolean isAbstract, Long plugid,
                                          Long cost, Long delay, List<Long> srlgs, String odu) {
        //NetworkLink
        KeyId linkId = TeMgrUtil.toNetworkLinkId(teLinkKey);
        NodeTpKey source = TeMgrUtil.nodeTpKey(teLinkKey);
        NodeTpKey destination = null;
        if (peerTeLinkKey != null) {
            destination = TeMgrUtil.nodeTpKey(peerTeLinkKey);
        }
        List<NetworkLinkKey> supportingLinkIds = null;
        if (supportTeLinkId != null) {
            supportingLinkIds = Lists
                    .newArrayList(TeMgrUtil.networkLinkKey(supportTeLinkId));
        }
        BitSet flags = new BitSet(TeConstants.FLAG_MAX_BITS);
        if (isAbstract) {
            flags.set(TeLink.BIT_ABSTRACT);
        }
        ExternalLink externalLink = null;

        if (plugid != null) {
            // Inter-Domain Link
            flags.set(TeLink.BIT_ACCESS_INTERDOMAIN);
            externalLink = new ExternalLink(null, plugid);
        }
        UnderlayPath underlayPath = null;
        Long adminGroup = null;
        List<Long> interLayerLocks = null;
        teLink = new DefaultTeLink(teLinkKey, peerTeLinkKey, underlayTopologyId,
                                          supportTeLinkId, sourceTeLinkId,
                                          new CommonLinkData(TeStatus.UP, TeStatus.UP, flags,
                                                             SwitchingType.OTN_TDM_CAPABLE,
                                                             EncodingType.LSP_ENCODING_ODUK,
                                                             externalLink, underlayPath,
                                                             new TePathAttributes(cost, delay, srlgs),
                                                             adminGroup, interLayerLocks, linkBwBuilder(odu)));
        return new DefaultNetworkLink(linkId, source, destination, supportingLinkIds, teLink);
    }

    private static Network networkBuilder(TeTopologyId teTopologyId, KeyId supportingNetworkId,
                                          Map<KeyId, NetworkNode> nodes,
                                          Map<KeyId, NetworkLink> links,
                                          boolean serverProvided,
                                          DeviceId ownerId,
                                          OptimizationType optType) {
        KeyId networkId = TeMgrUtil.toNetworkId(teTopologyId);
        List<KeyId> supportingNetworkIds = null;
        if (supportingNetworkId != null) {
            supportingNetworkIds = Lists.newArrayList(supportingNetworkId);
        }
        return new DefaultNetwork(networkId, supportingNetworkIds, nodes, links, teTopologyId,
                                  serverProvided, ownerId, optType);
    }

    /**
     * Returns the key for the sample TE Topology.
     *
     * @return value of TE Topology key
     */
    public static TeTopologyKey teTopologyKey() {
        return teTopologyKey;
    }

    /**
     * Returns the abstract TE Node in the sample TE Topology.
     *
     * @return value of TE node
     */
    public static TeNode teNode() {
        return teNode;
    }

    /**
     * Returns the TE link in the sample TE Topology.
     *
     * @return value of TE link
     */
    public static TeLink teLink() {
        return teLink;
    }

    /**
     * Builds a sample abstract TE Topology, which consists of one abstract node
     * representing an entire physical network, one inter-domain link and one
     * TTP.
     *
     * @return value of network with an abstract TE Topology
     */
    public static Network buildSampleAbstractNetwork() {
        TeTopologyKey underlayTopologyId = new TeTopologyKey(PROVIDER_ID,
                                                             CLIENT_NIL,
                                                             NATIVE_TOPOLOGY_ID);
        Map<KeyId, NetworkNode> nodes = Maps.newHashMap();
        networkNode = nodeBuilder(NODEIP, NUM_TPS, NUM_TTPS, underlayTopologyId,
                                  null, null, ABSTRACT);
        nodes.put(networkNode.nodeId(), networkNode);

        Map<KeyId, NetworkLink> links = Maps.newHashMap();
        TeLinkTpKey node1tp1 = new TeLinkTpKey(networkNode.teNode().teNodeId(),
                                               networkNode.teNode()
                                                       .teTerminationPointIds()
                                                       .get(FIRST_INDEX));
        networkLink = linkBuilder(node1tp1, null, null, null, null, UNABSTRACT,
                                  INTER_DOMAIN_LINK_PLUGID, LINK_COST,
                                  LINK_DELAY, Lists.newArrayList(LINK_SRLG),
                                  ODU4);
        links.put(networkLink.linkId(), networkLink);
        DeviceId ownerId = DeviceId.deviceId(DOMAIN_ID);
        TeTopologyId topologyId = new TeTopologyId(PROVIDER_ID, CLIENT_ID,
                                                   Long.toString(ABSTRACT_TOPOLOGY_ID));
        network = networkBuilder(topologyId, null, nodes, links, false,
                                 ownerId, OptimizationType.NOT_OPTIMIZED);
        return network;
    }

}
