/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.logging.log4j.core.time;

import org.apache.logging.log4j.util.PerformanceSensitive;

import java.io.Serializable;

/**
 * An instantaneous point on the time line, used for high-precision log event timestamps.
 * Modelled on <a href="https://docs.oracle.com/javase/9/docs/api/index.html?java/time/class-use/Instant.html">java.time.Instant</a>,
 * except that this version is mutable to prevent allocating temporary objects that need to be garbage-collected later.
 * <p>
 * Instances of this class are <em>not</em> thread-safe and should not be shared between threads.
 * </p>
 *
 * @since 2.11.0
 */
@PerformanceSensitive("allocation")
public class MutableInstant implements Instant, Serializable {

    private static final long serialVersionUID = 1L;
    private static final int MILLIS_PER_SECOND = 1000;
    private static final int NANOS_PER_MILLI = 1000_000;
    private static final int NANOS_PER_SECOND = MILLIS_PER_SECOND * NANOS_PER_MILLI;

    private long epochSecond;
    private int nanoOfSecond;

    @Override
    public long getEpochSecond() {
        return epochSecond;
    }

    @Override
    public int getNanoOfSecond() {
        return nanoOfSecond;
    }

    @Override
    public long getEpochMillisecond() {
        final int millis = nanoOfSecond / NANOS_PER_MILLI;
        return epochSecond * MILLIS_PER_SECOND + millis;
    }

    @Override
    public int getNanoOfMillisecond() {
        final int millis = nanoOfSecond / NANOS_PER_MILLI;
         // cheaper than nanoOfSecond % NANOS_PER_MILLI
        return nanoOfSecond - (millis * NANOS_PER_MILLI);
    }

    public void initFrom(final Instant other) {
        this.epochSecond = other.getEpochSecond();
        this.nanoOfSecond = other.getNanoOfSecond();
    }

    /**
     * Updates the fields of this {@code MutableInstant} from the specified epoch millis.
     * @param epochMilli the number of milliseconds from the Java epoch of 1970-01-01T00:00:00Z
     * @param nanoOfMillisecond the number of nanoseconds, later along the time-line, from the start of the millisecond
     */
    public void initFromEpochMilli(final long epochMilli, final int nanoOfMillisecond) {
        validateNanoOfMillisecond(nanoOfMillisecond);
        this.epochSecond = epochMilli / MILLIS_PER_SECOND;
        this.nanoOfSecond = (int) (epochMilli - (epochSecond * MILLIS_PER_SECOND)) * NANOS_PER_MILLI + nanoOfMillisecond;
    }

    private void validateNanoOfMillisecond(final int nanoOfMillisecond) {
        if (nanoOfMillisecond < 0 || nanoOfMillisecond >= NANOS_PER_MILLI) {
            throw new IllegalArgumentException("Invalid nanoOfMillisecond " + nanoOfMillisecond);
        }
    }

    public void initFrom(final Clock clock) {
        if (clock instanceof PreciseClock) {
            ((PreciseClock) clock).init(this);
        } else {
            initFromEpochMilli(clock.currentTimeMillis(), 0);
        }
    }

    /**
     * Updates the fields of this {@code MutableInstant} from the specified instant components.
     * @param epochSecond the number of seconds from the Java epoch of 1970-01-01T00:00:00Z
     * @param nano the number of nanoseconds, later along the time-line, from the start of the second
     */
    public void initFromEpochSecond(final long epochSecond, final int nano) {
        validateNanoOfSecond(nano);
        this.epochSecond = epochSecond;
        this.nanoOfSecond = nano;
    }

    private void validateNanoOfSecond(final int nano) {
        if (nano < 0 || nano >= NANOS_PER_SECOND) {
            throw new IllegalArgumentException("Invalid nanoOfSecond " + nano);
        }
    }

    /**
     * Updates the elements of the specified {@code long[]} result array from the specified instant components.
     * @param epochSecond (input) the number of seconds from the Java epoch of 1970-01-01T00:00:00Z
     * @param nano (input) the number of nanoseconds, later along the time-line, from the start of the second
     * @param result (output) a two-element array to store the result: the first element is the number of milliseconds
     *               from the Java epoch of 1970-01-01T00:00:00Z,
     *               the second element is the number of nanoseconds, later along the time-line, from the start of the millisecond
     */
    public static void instantToMillisAndNanos(final long epochSecond, final int nano, final long[] result) {
        int millis = nano / NANOS_PER_MILLI;
        result[0] = epochSecond * MILLIS_PER_SECOND + millis;
        result[1] = nano - (millis * NANOS_PER_MILLI); // cheaper than nanoOfSecond % NANOS_PER_MILLI
    }

    @Override
    public boolean equals(final Object object) {
        if (object == this) {
            return true;
        }
        if (!(object instanceof MutableInstant)) {
            return false;
        }
        MutableInstant other = (MutableInstant) object;
        return epochSecond == other.epochSecond && nanoOfSecond == other.nanoOfSecond;
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31 * result + (int) (epochSecond ^ (epochSecond >>> 32));
        result = 31 * result + nanoOfSecond;
        return result;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder(64);
        formatTo(sb);
        return sb.toString();
    }

    @Override
    public void formatTo(final StringBuilder buffer) {
        buffer.append("MutableInstant[epochSecond=").append(epochSecond).append(", nano=").append(nanoOfSecond).append("]");
    }
}
