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

import com.google.common.base.MoreObjects;
import com.google.common.collect.ComparisonChain;

/**
 * Class representing frequency. This class is intended to be used for a value whose unit is Hz
 * and its family (KHz, MHz, etc.).
 *
 * <p>
 * Note: this class is mainly intended to be used for lambda, which
 * represents THz order. Long has enough space to represent over THz frequency as Hz,
 * and the underlying value is long as Hz. This means this class can't represent
 * sub-Hz accuracy.
 * </p>
 */
public final class Frequency implements RichComparable<Frequency> {

    private static final long KHZ = 1_000L;
    private static final long MHZ = 1_000_000L;
    private static final long GHZ = 1_000_000_000L;
    private static final long THZ = 1_000_000_000_000L;

    private final long frequency;   // frequency in Hz

    /**
     * Creates an instance representing the specified frequency in Hz.
     *
     * @param frequency frequency in Hz
     */
    private Frequency(long frequency) {
        this.frequency = frequency;
    }

    /**
     * Return the value this instance represents as Hz.
     *
     * @return frequency in Hz
     */
    public long asHz() {
        return frequency;
    }

    /**
     * Returns an instance representing the specified value in Hz.
     *
     * @param value frequency in Hz
     * @return instance representing the given frequency
     */
    public static Frequency ofHz(long value) {
        return new Frequency(value);
    }

    /**
     * Returns an instance representing the specified value in KHz.
     *
     * @param value frequency in KHz
     * @return instance representing the given frequency
     */
    public static Frequency ofKHz(long value) {
        return new Frequency(value * KHZ);
    }

    /**
     * Returns an instance representing the specified value in KHz.
     *
     * @param value frequency in KHz
     * @return instance representing the given frequency
     */
    public static Frequency ofKHz(double value) {
        return new Frequency((long) (value * KHZ));
    }

    /**
     * Returns an instance representing the specified value in MHz.
     *
     * @param value frequency in MHz
     * @return instance representing the given frequency
     */
    public static Frequency ofMHz(long value) {
        return new Frequency(value * MHZ);
    }

    /**
     * Returns an instance representing the specified value in MHz.
     *
     * @param value frequency in MHz
     * @return instance representing the given frequency
     */
    public static Frequency ofMHz(double value) {
        return new Frequency((long) (value * MHZ));
    }

    /**
     * Returns an instance representing the specified value in GHz.
     *
     * @param value frequency in GHz
     * @return instance representing the given frequency
     */
    public static Frequency ofGHz(long value) {
        return new Frequency(value * GHZ);
    }

    /**
     * Returns an instance representing the specified value in GHz.
     *
     * @param value frequency in GHz
     * @return instance representing the given frequency
     */
    public static Frequency ofGHz(double value) {
        return new Frequency((long) (value * GHZ));
    }

    /**
     * Returns an instance representing the specified value in THz.
     *
     * @param value frequency in THz
     * @return instance representing the given frequency
     */
    public static Frequency ofTHz(long value) {
        return new Frequency(value * THZ);
    }

    /**
     * Returns an instance representing the specified value in THz.
     *
     * @param value frequency in THz
     * @return instance representing the given frequency
     */
    public static Frequency ofTHz(double value) {
        return new Frequency((long) (value * THZ));
    }

    /**
     * Returns a Frequency whose value is (this + value).
     *
     * @param value value to be added to this Frequency
     * @return this + value
     */
    public Frequency add(Frequency value) {
        return new Frequency(this.frequency + value.frequency);
    }

    /**
     * Returns a Frequency whose value is (this - value).
     *
     * @param value value to be subtracted from this Frequency
     * @return this - value
     */
    public Frequency subtract(Frequency value) {
        return new Frequency(this.frequency - value.frequency);
    }

    /**
     * Returns a Frequency whose value is (this * value).
     *
     * @param value value to be multiplied by this Frequency
     * @return this * value
     */
    public Frequency multiply(long value) {
        return new Frequency(this.frequency * value);
    }

    /**
     * Returns a Frequency whose value is Math.floorDiv(this, value).
     *
     * @param value value to be divided by this Frequency
     * @return Math.floorDiv(this, value)
     */
    public Frequency floorDivision(long value) {
        return new Frequency(Math.floorDiv(this.frequency, value));
    }

    @Override
    public int compareTo(Frequency other) {
        return ComparisonChain.start()
                .compare(this.frequency, other.frequency)
                .result();
    }

    @Override
    public int hashCode() {
        return Long.hashCode(frequency);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (!(obj instanceof Frequency)) {
            return false;
        }

        final Frequency other = (Frequency) obj;
        return this.frequency == other.frequency;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("frequency", frequency + "Hz")
                .toString();
    }
}
