/*
 * Copyright 2016 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.teyang.utils.topology;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.util.List;

import org.onosproject.tetopology.management.api.KeyId;
import org.onosproject.tetopology.management.api.link.NetworkLink;
import org.onosproject.tetopology.management.api.node.NetworkNode;
import org.onosproject.teyang.api.OperationType;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.DefaultNetworks;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.DefaultNetworks.OnosYangNodeOperationType;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.DefaultNetworksState;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.NetworkId;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.Networks;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.NetworksState;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.DefaultNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.Network;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.Network.NetworkBuilder;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.network.DefaultNetworkTypes;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.network.DefaultSupportingNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208.ietfnetwork.networks.network.DefaultSupportingNetwork.SupportingNetworkBuilder;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.network.NetworkTypes;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.network.Node;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
        .ietfnetwork.networks.network.SupportingNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev20151208
        .ietfnetworktopology.networks.network.AugmentedNdNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev20151208
        .ietfnetworktopology.networks.network.DefaultAugmentedNdNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev20151208.ietfnetworktopology.networks.network.DefaultAugmentedNdNetwork.AugmentedNdNetworkBuilder;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.topology.rev20151208
        .ietfnetworktopology.networks.network.augmentedndnetwork.Link;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.AugmentedNwNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.DefaultAugmentedNwNetwork;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.augmentednwnetwork.DefaultTe;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.augmentednwnetwork.Te;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.networktypes.AugmentedNwNetworkTypes;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.networktypes.DefaultAugmentedNwNetworkTypes;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.networktypes.augmentednwnetworktypes.DefaultTeTopology;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.topology.rev20160708
        .ietftetopology.networks.network.networktypes.augmentednwnetworktypes.TeTopology;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.types.rev20160705
        .ietftetypes.TeGlobalId;
import org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.te.types.rev20160705
        .ietftetypes.TeTopologyId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;


/**
 * Networks, Networks State conversion functions.
 */
public final class NetworkConverter {
    private static final String
        E_NULL_TE_NETWORKS = "TeSubsystem networks cannot be null";
    private static final String
        E_NULL_TE_NETWORK_LIST = "TeSubsystem network list cannot be null";
    private static final String
        E_NULL_TE_NETWORK = "TeSubsystem network cannot be null";
    private static final String
        E_NULL_TE_NETWORKID = "TeSubsystem networkId cannot be null";
    private static final String
        E_NULL_YANG_NETWORKS = "YANG networks cannot be null";
    private static final String
        E_NULL_YANG_NETWORK_LIST = "YANG network list cannot be null";
    private static final String
        E_NULL_YANG_NETWORK = "YANG network cannot be null";
    private static final String
        E_NULL_YANG_NETWORKID = "YANG networkId cannot be null";
    private static final String
        E_NULL_YANG_NETWORKSSTATE = "YANG networksState cannot be null";
    private static final String
        E_DIFF_YANG_NETWORKID = "YANG networkId must be same in Network and NetworkState";
    private static final String
        E_NULL_YANG_NETWORKSSTATE_NETWORK = "YANG networksState network cannot be null";
    private static final String
        E_NULL_YANG_NETWORKSSTATE_NETWORKREF = "YANG networksState networkRef cannot be null";

    private static final Logger log = LoggerFactory.getLogger(NetworkConverter.class);

    // no instantiation
    private NetworkConverter() {
    }

    private static OnosYangNodeOperationType toNetworksOperationType(OperationType operation) {
        switch (operation) {
        case CREATE:
            return OnosYangNodeOperationType.CREATE;

        case DELETE:
            return OnosYangNodeOperationType.DELETE;

        case REMOVE:
            return OnosYangNodeOperationType.REMOVE;

        case MERGE:
            return OnosYangNodeOperationType.MERGE;

        case REPLACE:
            return OnosYangNodeOperationType.REPLACE;

        default:
            return OnosYangNodeOperationType.NONE;
        }
    }

    /**
     * Networks object conversion from TE Topology subsystem to YANG.
     *
     * @param teSubsystem TE Topology subsystem networks object
     * @param operation operation type
     * @return Networks YANG object
     */
    public static Networks teSubsystem2YangNetworks(
            org.onosproject.tetopology.management.api.Networks teSubsystem,
            OperationType operation) {
        checkNotNull(teSubsystem, E_NULL_TE_NETWORKS);
        checkNotNull(teSubsystem.networks(), E_NULL_TE_NETWORK_LIST);
        Networks.NetworksBuilder builder =
                DefaultNetworks.builder().onosYangNodeOperationType(toNetworksOperationType(operation));
        List<Network> networks = Lists.newArrayList();
        for (org.onosproject.tetopology.management.api.Network teNetwork : teSubsystem.networks()) {
            networks.add(teSubsystem2YangNetwork(teNetwork, operation));
        }
        builder.network(networks);
        return builder.build();
    }

    private static DefaultNetworksState.OnosYangNodeOperationType
                           toNetworksStateOperationType(OperationType operation) {
        switch (operation) {
        case CREATE:
            return DefaultNetworksState.OnosYangNodeOperationType.CREATE;

        case DELETE:
            return DefaultNetworksState.OnosYangNodeOperationType.DELETE;

        case REMOVE:
            return DefaultNetworksState.OnosYangNodeOperationType.REMOVE;

        case MERGE:
            return DefaultNetworksState.OnosYangNodeOperationType.MERGE;

        case REPLACE:
            return DefaultNetworksState.OnosYangNodeOperationType.REPLACE;

        default:
            return DefaultNetworksState.OnosYangNodeOperationType.NONE;
        }
    }

    /**
     * Network States object conversion from TE Topology subsystem to YANG.
     *
     * @param teSubsystem TE Topology subsystem networks object
     * @param operation operation type
     * @return NetworkStates YANG object
     */
    public static NetworksState teSubsystem2YangNetworkStates(
            org.onosproject.tetopology.management.api.Networks teSubsystem,
            OperationType operation) {
        checkNotNull(teSubsystem, "teSubsystem object cannot be null");
        checkNotNull(teSubsystem.networks(), "TeSubsystem Networks object cannot be null");
        NetworksState.NetworksStateBuilder builder =
                DefaultNetworksState.builder().onosYangNodeOperationType(toNetworksStateOperationType(operation));
        List<org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
                .ietfnetwork.networksstate.Network> networks = Lists.newArrayList();
        for (org.onosproject.tetopology.management.api.Network teNetwork : teSubsystem.networks()) {
            networks.add(teSubsystem2YangNetworkState(teNetwork, operation));
        }
        builder.network(networks);
        return builder.build();
    }

    private static org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
            .ietfnetwork.networksstate.Network networkStateNetwork(Network network,
                                                                   NetworksState yangNetworkStates) {
        checkNotNull(network, "YANG Network object cannot be null");
        checkNotNull(yangNetworkStates, "YANG NetworksState object cannot be null");
        if (yangNetworkStates.network() == null) {
            return null;
        }

        for (org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
                .ietfnetwork.networksstate.Network stateNetwork : yangNetworkStates.network()) {
            if (stateNetwork.networkRef().equals(network.networkId())) {
                return stateNetwork;
            }
        }
        return null;
    }

    /**
     * Networks object conversion from YANG to TE Topology subsystem.
     *
     * @param yangNetworks Networks YANG object
     * @param yangNetworkStates NetworkStates YANG object
     * @return teSubsystem TE Topology subsystem networks object
     */
    public static org.onosproject.tetopology.management.api.Networks yang2TeSubsystemNetworks(
            Networks yangNetworks, NetworksState yangNetworkStates) {
        checkNotNull(yangNetworks, E_NULL_YANG_NETWORKS);
        checkNotNull(yangNetworks.network(), E_NULL_YANG_NETWORK_LIST);
        checkNotNull(yangNetworkStates, E_NULL_YANG_NETWORKSSTATE);

        org.onosproject.tetopology.management.api.DefaultNetworks defaultNetworks =
                new org.onosproject.tetopology.management.api.DefaultNetworks();
        List<org.onosproject.tetopology.management.api.Network> networks = Lists.newArrayList();
        for (Network network : yangNetworks.network()) {
            org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
                    .ietfnetwork.networksstate.Network stateNetwork =
                            networkStateNetwork(network, yangNetworkStates);
            org.onosproject.tetopology.management.api.Network teNetwork;
            if (stateNetwork == null) {
                log.info("networkId {} can't be found in yangNetworkStates",
                          network.networkId());
                teNetwork = yang2TeSubsystemNetwork(network);
            } else {
                teNetwork = yang2TeSubsystemNetwork(network, stateNetwork);
            }
            networks.add(teNetwork);
        }

        defaultNetworks.setNetworks(networks);
        return defaultNetworks;
    }

    private static DefaultNetwork.OnosYangNodeOperationType toNetworkOperationType(OperationType operation) {
        switch (operation) {
        case CREATE:
            return DefaultNetwork.OnosYangNodeOperationType.CREATE;

        case DELETE:
            return DefaultNetwork.OnosYangNodeOperationType.DELETE;

        case REMOVE:
            return DefaultNetwork.OnosYangNodeOperationType.REMOVE;

        case MERGE:
            return DefaultNetwork.OnosYangNodeOperationType.MERGE;

        case REPLACE:
            return DefaultNetwork.OnosYangNodeOperationType.REPLACE;

        default:
            return DefaultNetwork.OnosYangNodeOperationType.NONE;
        }
    }

    private static NetworkBuilder te2YangSupportingNetwork(NetworkBuilder builder,
                                                           List<KeyId> teSpptNetworkIds) {
        List<SupportingNetwork> snws = Lists.newArrayList();
        SupportingNetworkBuilder spNetworkBuilder = DefaultSupportingNetwork.builder();
        for (KeyId teSpNwKey : teSpptNetworkIds) {
            snws.add(spNetworkBuilder
                    .networkRef(NetworkId.fromString(teSpNwKey.toString()))
                    .build());
        }
        return builder.supportingNetwork(snws);
    }

    private static NetworkBuilder te2YangNodes(NetworkBuilder builder,
                                               List<NetworkNode> teNodes) {
        List<Node> nodeList = Lists.newArrayList();
        // Add each node
        for (org.onosproject.tetopology.management.api.node.NetworkNode node : teNodes) {
            // Convert the te node to a YO.
            nodeList.add(NodeConverter.teSubsystem2YangNode(node));
        }
        return builder.node(nodeList);
    }

    private static NetworkBuilder te2YangLinks(NetworkBuilder builder,
                                               List<NetworkLink> teLinks) {
        List<Link> linkList = Lists.newArrayList();
        // Add each link
        for (org.onosproject.tetopology.management.api.link.NetworkLink link : teLinks) {
            // Convert the te link to a YO
            linkList.add(LinkConverter.teSubsystem2YangLink(link));
        }
        AugmentedNdNetworkBuilder ndAugment = DefaultAugmentedNdNetwork.builder();
        ndAugment.link(linkList);
        builder.addYangAugmentedInfo(ndAugment.build(), AugmentedNdNetwork.class);
        return builder;
    }

    private static NetworkBuilder te2YangNetworkType(NetworkBuilder builder,
                org.onosproject.tetopology.management.api.TeTopologyId teTopologyId) {
        NetworkTypes.NetworkTypesBuilder nwType = DefaultNetworkTypes.builder();
        if (teTopologyId != null) {
            // Set "te-topology" network type.
            TeTopology.TeTopologyBuilder teTopology = DefaultTeTopology.builder();
            AugmentedNwNetworkTypes.AugmentedNwNetworkTypesBuilder teNwType =
                    DefaultAugmentedNwNetworkTypes.builder();
            teNwType.teTopology(teTopology.build());
            nwType.addYangAugmentedInfo(teNwType.build(), AugmentedNwNetworkTypes.class);
        }
        return builder.networkTypes(nwType.build());
    }

    private static NetworkBuilder te2YangTopologyIds(NetworkBuilder builder,
            org.onosproject.tetopology.management.api.TeTopologyId teTopologyId) {
        Te.TeBuilder teBuilder = DefaultTe.builder();
        teBuilder.clientId(new TeGlobalId(teTopologyId.clientId()));
        teBuilder.providerId(new TeGlobalId(teTopologyId.providerId()));
        if (teTopologyId.topologyId() !=  null) {
            teBuilder.teTopologyId(new TeTopologyId(teTopologyId.topologyId()));
        }

        AugmentedNwNetwork.AugmentedNwNetworkBuilder nwAugment = DefaultAugmentedNwNetwork
                .builder();
        nwAugment.te(teBuilder.build());
        builder.addYangAugmentedInfo(nwAugment.build(),
                                            AugmentedNwNetwork.class);
        return builder;
    }

    /**
     * Network object conversion from TE Topology subsystem to YANG.
     *
     * @param teSubsystem TE Topology subsystem network object
     * @param operation operation type
     * @return Network YANG object
     */
    public static Network teSubsystem2YangNetwork(
            org.onosproject.tetopology.management.api.Network teSubsystem,
            OperationType operation) {
        checkNotNull(teSubsystem, E_NULL_TE_NETWORK);
        checkNotNull(teSubsystem.networkId(), E_NULL_TE_NETWORKID);

        // Generate a network builder with the specific networkId.
        NetworkId networkId = NetworkId.fromString(teSubsystem.networkId().toString());
        NetworkBuilder builder = DefaultNetwork.builder()
                                               .onosYangNodeOperationType(
                                                       toNetworkOperationType(operation))
                                               .networkId(networkId);

        // Supporting networks
        if (teSubsystem.getSupportingNetworkIds() != null) {
            builder = te2YangSupportingNetwork(builder, teSubsystem.getSupportingNetworkIds());
        }

        // Nodes
        if (teSubsystem.getNodes() != null) {
            builder = te2YangNodes(builder, teSubsystem.getNodes());
        }

        // Network types
        builder = te2YangNetworkType(builder, teSubsystem.getTeTopologyId());

        // Add links - link is the augmentation
        if (teSubsystem.getLinks() != null) {
            builder = te2YangLinks(builder, teSubsystem.getLinks());
        }

        // TE Topology IDs
        if (teSubsystem.getTeTopologyId() != null) {
            builder = te2YangTopologyIds(builder, teSubsystem.getTeTopologyId());
        }

        return builder.build();
    }

    /**
     * Network State object conversion from TE Topology subsystem to YANG.
     *
     * @param teSubsystem TE Topology subsystem network object
     * @param operation operation type
     * @return Network YANG object
     */
    public static org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network
                        .rev20151208.ietfnetwork.networksstate.Network
            teSubsystem2YangNetworkState(
                    org.onosproject.tetopology.management.api.Network teSubsystem,
                    OperationType operation) {
        checkNotNull(teSubsystem, E_NULL_TE_NETWORK);
        checkNotNull(teSubsystem.networkId(), E_NULL_TE_NETWORKID);

        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
                .ietfnetwork.networksstate.Network.NetworkBuilder stateBuilder =
        org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208
                .ietfnetwork.networksstate.DefaultNetwork.builder();

        if (teSubsystem.networkId() != null) {
            stateBuilder.networkRef(NetworkId.fromString(teSubsystem.networkId().toString()));
        }
        stateBuilder.serverProvided(teSubsystem.isServerProvided());

        // Operation type may be required.
        return stateBuilder.build();
    }


    /**
     * Network conversion from YANG to TE Topology subsystem.
     *
     * @param yangNetwork Network YANG object
     * @return TE Topology subsystem defaultNetwork object
     */
    private static org.onosproject.tetopology.management.api.DefaultNetwork yang2TeDefaultNetwork(
            Network yangNetwork) {
        checkNotNull(yangNetwork, E_NULL_YANG_NETWORK);
        checkNotNull(yangNetwork.networkId(), E_NULL_YANG_NETWORKID);
        String networkId = yangNetwork.networkId().uri().string();
        org.onosproject.tetopology.management.api.DefaultNetwork teNetwork =
                new org.onosproject.tetopology.management.api.DefaultNetwork(KeyId.keyId(networkId));

        // Supporting networks
        if (yangNetwork.supportingNetwork() != null) {
            List<KeyId> supportingNetworkIds = Lists.newArrayList();
            for (SupportingNetwork supportNw : yangNetwork.supportingNetwork()) {
                supportingNetworkIds.add(
                        KeyId.keyId(supportNw.networkRef().uri().string()));
            }
            teNetwork.setSupportingNetworkIds(supportingNetworkIds);
        }

        // Nodes
        if (yangNetwork.node() != null) {
            List<org.onosproject.tetopology.management.api.node.NetworkNode>
                teNodes = Lists.newArrayList();
            for (Node node : yangNetwork.node()) {
                // Convert the Yang Node to a TE node.
                teNodes.add(NodeConverter.yang2TeSubsystemNode(node, yangNetwork.networkId()));
            }
            teNetwork.setNodes(teNodes);
        }

        // Links
        if (yangNetwork.yangAugmentedInfo(AugmentedNdNetwork.class) != null) {
            AugmentedNdNetwork augmentLink =
                    (AugmentedNdNetwork) yangNetwork.yangAugmentedInfo(AugmentedNdNetwork.class);
            List<org.onosproject.tetopology.management.api.link.NetworkLink>
                teLinks = Lists.newArrayList();
            for (Link link : augmentLink.link()) {
                // Convert the Yang Link to a TE link.
                teLinks.add(LinkConverter.yang2TeSubsystemLink(link, yangNetwork.networkId()));
            }
            teNetwork.setLinks(teLinks);
        }

        // TE Topology Ids
        if (yangNetwork.yangAugmentedInfo(AugmentedNwNetwork.class) != null) {
            AugmentedNwNetwork augmentTeIds =
                    (AugmentedNwNetwork) yangNetwork.yangAugmentedInfo(AugmentedNwNetwork.class);
            org.onosproject.tetopology.management.api.TeTopologyId teTopologyId =
                    new org.onosproject.tetopology.management.api.TeTopologyId(
                            augmentTeIds.te().clientId().uint32(),
                            augmentTeIds.te().providerId().uint32(),
                            augmentTeIds.te().teTopologyId().string());

            teNetwork.setTeTopologyId(teTopologyId);
        }

        return teNetwork;
    }

    /**
     * Network object conversion from YANG to TE Topology subsystem.
     *
     * @param yangNetwork Network YANG object
     * @return network TE Topology subsystem networks object
     */
    public static org.onosproject.tetopology.management.api.Network yang2TeSubsystemNetwork(Network yangNetwork) {
       return yang2TeDefaultNetwork(yangNetwork);
    }

    /**
     * Network and State object conversion from YANG to TE Topology subsystem.
     *
     * @param yangNetwork Network YANG object
     * @param yangNetworkState NetworkState YANG object
     * @return teSubsystem TE Topology subsystem networks object
     */
    public static org.onosproject.tetopology.management.api.Network yang2TeSubsystemNetwork(Network yangNetwork,
            org.onosproject.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev20151208.ietfnetwork
                    .networksstate.Network yangNetworkState) {
        org.onosproject.tetopology.management.api.DefaultNetwork teNetwork =
                yang2TeDefaultNetwork(yangNetwork);

        checkNotNull(yangNetworkState, E_NULL_YANG_NETWORKSSTATE_NETWORK);
        checkNotNull(yangNetworkState.networkRef(), E_NULL_YANG_NETWORKSSTATE_NETWORKREF);
        String networkref = yangNetworkState.networkRef().uri().string();
        checkState(teNetwork.networkId().toString().equals(networkref),
                   E_DIFF_YANG_NETWORKID);

        teNetwork.setServerProvided(yangNetworkState.serverProvided());

        return teNetwork;
    }
}


