/*
 * Copyright 2015-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.ui.topo;

import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;

import java.text.DecimalFormat;

import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.net.LinkKey.linkKey;

/**
 * Utility methods for helping out with formatting data for the Topology View
 * in the web client.
 */
public final class TopoUtils {

    // explicit decision made to not 'javadoc' these constants
    public static final double N_KILO = 1024;
    public static final double N_MEGA = 1024 * N_KILO;
    public static final double N_GIGA = 1024 * N_MEGA;

    public static final String BITS_UNIT = "b";
    public static final String BYTES_UNIT = "B";
    public static final String PACKETS_UNIT = "p";

    private static final DecimalFormat DF2 = new DecimalFormat("#,###.##");

    private static final String COMPACT = "%s/%s-%s/%s";
    private static final String EMPTY = "";
    private static final String SPACE = " ";
    private static final String FLOW = "flow";
    private static final String FLOWS = "flows";

    // non-instantiable
    private TopoUtils() { }

    /**
     * Returns a compact identity for the given link, in the form
     * used to identify links in the Topology View on the client.
     *
     * @param link link
     * @return compact link identity
     */
    public static String compactLinkString(Link link) {
        return String.format(COMPACT, link.src().elementId(), link.src().port(),
                link.dst().elementId(), link.dst().port());
    }

    /**
     * Produces a canonical link key, that is, one that will match both a link
     * and its inverse.
     *
     * @param link the link
     * @return canonical key
     */
    public static LinkKey canonicalLinkKey(Link link) {
        String sn = link.src().elementId().toString();
        String dn = link.dst().elementId().toString();
        return sn.compareTo(dn) < 0 ?
                linkKey(link.src(), link.dst()) : linkKey(link.dst(), link.src());
    }

    /**
     * Returns a value representing a count of bytes.
     *
     * @param bytes number of bytes
     * @return value representing bytes
     */
    public static ValueLabel formatBytes(long bytes) {
        return new ValueLabel(bytes, BYTES_UNIT);
    }

    /**
     * Returns a value representing a count of packets per second.
     *
     * @param packets number of packets (per second)
     * @return value representing packets per second
     */
    public static ValueLabel formatPacketRate(long packets) {
        return new ValueLabel(packets, PACKETS_UNIT).perSec();
    }


    /**
     * Returns a value representing a count of bits per second,
     * (clipped to a maximum of 10 Gbps).
     * Note that the input is bytes per second.
     *
     * @param bytes bytes per second
     * @return value representing bits per second
     */
    public static ValueLabel formatClippedBitRate(long bytes) {
        return new ValueLabel(bytes * 8, BITS_UNIT).perSec().clipG(10.0);
    }

    /**
     * Returns human readable flow count, to be displayed as a label.
     *
     * @param flows number of flows
     * @return formatted flow count
     */
    public static String formatFlows(long flows) {
        if (flows < 1) {
            return EMPTY;
        }
        return String.valueOf(flows) + SPACE + (flows > 1 ? FLOWS : FLOW);
    }


    /**
     * Enumeration of magnitudes.
     */
    public enum Magnitude {
        ONE("", 1),
        KILO("K", N_KILO),
        MEGA("M", N_MEGA),
        GIGA("G", N_GIGA);

        private final String label;
        private final double mult;

        Magnitude(String label, double mult) {
            this.label = label;
            this.mult = mult;
        }

        @Override
        public String toString() {
            return label;
        }

        private double mult() {
            return mult;
        }
    }


    /**
     * Encapsulates a value to be used as a label.
     */
    public static class ValueLabel {
        private final long value;
        private final String unit;

        private double divDown;
        private Magnitude mag;

        private boolean perSec = false;
        private boolean clipped = false;

        /**
         * Creates a value label with the given base value and unit. For
         * example:
         * <pre>
         * ValueLabel bits = new ValueLabel(2_050, "b");
         * ValueLabel bytesPs = new ValueLabel(3_000_000, "B").perSec();
         * </pre>
         * Generating labels:
         * <pre>
         *   bits.toString()     ...  "2.00 Kb"
         *   bytesPs.toString()  ...  "2.86 MBps"
         * </pre>
         *
         * @param value the base value
         * @param unit  the value unit
         */
        public ValueLabel(long value, String unit) {
            this.value = value;
            this.unit = unit;
            computeAdjusted();
        }

        private void computeAdjusted() {
            if (value >= N_GIGA) {
                divDown = value / N_GIGA;
                mag = Magnitude.GIGA;
            } else if (value >= N_MEGA) {
                divDown = value / N_MEGA;
                mag = Magnitude.MEGA;
            } else if (value >= N_KILO) {
                divDown = value / N_KILO;
                mag = Magnitude.KILO;
            } else {
                divDown = value;
                mag = Magnitude.ONE;
            }
        }

        /**
         * Mark this value to be expressed as a rate. That is, "ps" (per sec)
         * will be appended in the string representation.
         *
         * @return self, for chaining
         */
        public ValueLabel perSec() {
            perSec = true;
            return this;
        }

        /**
         * Clips the (adjusted) value to the given threshold expressed in
         * Giga units. That is, if the adjusted value exceeds the threshold,
         * it will be set to the threshold value and the clipped flag
         * will be set. For example,
         * <pre>
         * ValueLabel tooMuch = new ValueLabel(12_000_000_000, "b")
         *      .perSec().clipG(10.0);
         *
         * tooMuch.toString()    ...  "10.00 Gbps"
         * tooMuch.clipped()     ...  true
         * </pre>
         *
         * @param threshold the clip threshold (Giga)
         * @return self, for chaining
         */
        public ValueLabel clipG(double threshold) {
            return clip(threshold, Magnitude.GIGA);
        }

        private ValueLabel clip(double threshold, Magnitude m) {
            checkArgument(threshold >= 1.0, "threshold must be 1.0 or more");
            double clipAt = threshold * m.mult();
            if (value > clipAt) {
                divDown = threshold;
                mag = m;
                clipped = true;
            }
            return this;
        }

        /**
         * Returns true if this value was clipped to a maximum threshold.
         *
         * @return true if value was clipped
         */
        public boolean clipped() {
            return clipped;
        }

        /**
         * Returns the magnitude value.
         *
         * @return the magnitude
         */
        public Magnitude magnitude() {
            return mag;
        }

        @Override
        public String toString() {
            return DF2.format(divDown) + SPACE + mag + unit + (perSec ? "ps" : "");
        }
    }
}
