/*
 * Copyright 2020-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.net.behaviour.inbandtelemetry;

import com.google.common.annotations.Beta;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.TpPort;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.config.Config;
import org.onosproject.ui.JsonUtils;

/**
 * Application level configuration of the INT process.
 * Config example:
 * {
 *   "apps": {
 *     "org.onosproject.inbandtelemetry": {
 *       "report": {
 *         "collectorIp": "192.168.0.1",
 *         "collectorPort": 5500,
 *         "minFlowHopLatencyChangeNs": 300
 *       }
 *     }
 *   }
 * }
 */
@Beta
public final class IntReportConfig extends Config<ApplicationId> {
    private static final String COLLECTOR_IP = "collectorIp";
    private static final String COLLECTOR_PORT = "collectorPort";
    private static final String MIN_FLOW_HOP_LATENCY_CHANGE_NS = "minFlowHopLatencyChangeNs";
    private static final String COLLECTOR_NEXT_HOP_MAC = "collectorNextHopMac";
    private static final String SINK_IP = "sinkIp";
    private static final String SINK_MAC = "sinkMac";

    /**
     * IP address of the collector.
     * This is the destination IP address that will be used for all INT reports
     * generated by all INT devices.
     *
     * @return collector IP address, null if not present
     */
    public IpAddress collectorIp() {
        if (object.hasNonNull(COLLECTOR_IP)) {
            return IpAddress.valueOf(JsonUtils.string(object, COLLECTOR_IP));
        } else {
            return null;
        }
    }

    /**
     * UDP port number of the collector.
     * This is the destination UDP port number that will be used for all INT reports
     * generated by all INT devices.
     *
     * @return collector UDP port number, null if not present
     */
    public TpPort collectorPort() {
        if (object.hasNonNull(COLLECTOR_PORT)) {
            return TpPort.tpPort((int) JsonUtils.number(object, COLLECTOR_PORT));
        } else {
            return null;
        }
    }

    /**
     * Gets the minimal interval of hop latency change for a flow.
     * This value is used to instruct an INT-capable device to produce reports
     * only for packets which hop latency changed by at least minFlowHopLatencyChangeNs
     * from the previously reported value for the same flow (5-tuple), i.e., produce a
     * report only if `(currentHopLatency - previousHopLatency) > minFlowHopLatencyChangeNs`.
     * Some device implementations might support only specific intervals, e.g., powers of 2.
     *
     * @return Interval in nanoseconds
     */
    public int minFlowHopLatencyChangeNs() {
        if (object.hasNonNull(MIN_FLOW_HOP_LATENCY_CHANGE_NS)) {
            return (int) JsonUtils.number(object, MIN_FLOW_HOP_LATENCY_CHANGE_NS);
        } else {
            return 0;
        }
    }

    /**
     * Returns MAC address of next hop of INT report packets.
     * This can be either MAC address of the collector or a router.
     * This is an optional parameter, which means that the usage of this
     * parameter depends on IntProgrammable implementation.
     * (e.g., If a report packet needs to be routed to reach the collector,
     * IntProgrammable will ignore this value and choose next hop router's MAC address.
     * If a collector itself is the next hop of INT report packets, then
     * this value will be used as a destination MAC address for all INT report packets.)
     *
     * @return MAC address of next hop of INT report packets, null if not present
     */
    public MacAddress collectorNextHopMac() {
        if (object.hasNonNull(COLLECTOR_NEXT_HOP_MAC)) {
            return MacAddress.valueOf(JsonUtils.string(object, COLLECTOR_NEXT_HOP_MAC));
        } else {
            return null;
        }
    }

    /**
     * Returns IP address of the sink device.
     * All sink devices share this address as the source IP address
     * for all INT reports.
     *
     * @return sink device's IP address, null if not present
     */
    public IpAddress sinkIp() {
        if (object.hasNonNull(SINK_IP)) {
            return IpAddress.valueOf(JsonUtils.string(object, SINK_IP));
        } else {
            return null;
        }
    }

    /**
     * Returns MAC address of the sink device.
     * All sink devices share this address as the source MAC address
     * for all INT reports.
     *
     * @return sink device's MAC address, null if not present
     */
    public MacAddress sinkMac() {
        if (object.hasNonNull(SINK_MAC)) {
            return MacAddress.valueOf(JsonUtils.string(object, SINK_MAC));
        } else {
            return null;
        }
    }

    /**
     * Sets the collector IP to the config.
     *
     * @param collectorIp the collector IP
     * @return the config
     */
    public IntReportConfig setCollectorIp(IpAddress collectorIp) {
        return (IntReportConfig) setOrClear(COLLECTOR_IP, collectorIp.toString());
    }

    /**
     * Sets the collector port to the config.
     *
     * @param port the collector port
     * @return the config
     */
    public IntReportConfig setCollectorPort(TpPort port) {
        return (IntReportConfig) setOrClear(COLLECTOR_PORT, port.toInt());
    }

    /**
     * Sets the minimal interval of hop latency change
     * for a flow to the config.
     *
     * @param ns the value of hop latency change
     * @return the config
     */
    public IntReportConfig setMinFlowHopLatencyChangeNs(int ns) {
        return (IntReportConfig) setOrClear(MIN_FLOW_HOP_LATENCY_CHANGE_NS, ns);
    }

    /**
     * Sets collector next hop mac address to the config.
     *
     * @param collectorNextHopMac the collector next hop mac address
     * @return the config
     */
    public IntReportConfig setCollectorNextHopMac(MacAddress collectorNextHopMac) {
        return (IntReportConfig) setOrClear(COLLECTOR_NEXT_HOP_MAC, collectorNextHopMac.toString());
    }

    /**
     * Sets the sink IP address to the config.
     *
     * @param sinkIp the sink IP address
     * @return the config
     */
    public IntReportConfig setSinkIp(IpAddress sinkIp) {
        return (IntReportConfig) setOrClear(SINK_IP, sinkIp.toString());
    }

    /**
     * Sets the sink mac address to the config.
     *
     * @param sinkMac the sink mac address
     * @return the config
     */
    public IntReportConfig setSinkMac(MacAddress sinkMac) {
        return (IntReportConfig) setOrClear(SINK_MAC, sinkMac.toString());
    }
}
