/*
 * 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.geronimo.microprofile.metrics.common;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.LongStream;
import java.util.stream.Stream;

import javax.json.bind.annotation.JsonbTransient;

import org.eclipse.microprofile.metrics.Histogram;
import org.eclipse.microprofile.metrics.Snapshot;

// todo? rework it to use the classical exponential decay impl?
public class HistogramImpl implements Histogram {
    private static final long INTERVAL_NS = TimeUnit.MINUTES.toNanos(1);
    private static final Value[] EMPTY_VALUES_ARRAY = new Value[0];

    private final String unit;
    private final LongAdder count = new LongAdder();
    private final Collection<Value> values = new CopyOnWriteArrayList<>();
    private final AtomicLong lastCleanUp = new AtomicLong(System.nanoTime());

    public HistogramImpl(final String unit) {
        this.unit = unit;
    }

    @Override
    public void update(final int value) {
        update((long) value);
    }

    @Override
    public synchronized void update(final long value) {
        refresh();
        count.increment();
        values.add(new Value(System.nanoTime(), value));
    }

    @Override
    public long getCount() {
        return count.sum();
    }

    @Override
    @JsonbTransient
    public Snapshot getSnapshot() {
        refresh();
        return new SnapshotImpl(values.toArray(EMPTY_VALUES_ARRAY));
    }

    public String getUnit() {
        return unit;
    }

    public double getP50() {
        return getSnapshot().getMedian();
    }

    public double getP75() {
        return getSnapshot().get75thPercentile();
    }

    public double getP95() {
        return getSnapshot().get95thPercentile();
    }

    public double getP98() {
        return getSnapshot().get98thPercentile();
    }

    public double getP99() {
        return getSnapshot().get99thPercentile();
    }

    public double getP999() {
        return getSnapshot().get999thPercentile();
    }

    public long getMax() {
        return getSnapshot().getMax();
    }

    public double getMean() {
        return getSnapshot().getMean();
    }

    public long getMin() {
        return getSnapshot().getMin();
    }

    public double getStddev() {
        return getSnapshot().getStdDev();
    }

    // cheap way to avoid to explode the mem for nothing
    private void refresh() {
        final long now = System.nanoTime();
        final long lastUpdateNs = lastCleanUp.get();
        final long elaspsedTime = now - lastUpdateNs;
        if (elaspsedTime > INTERVAL_NS && lastCleanUp.compareAndSet(lastUpdateNs, now)) {
            final long cleanFrom = now - INTERVAL_NS;
            values.removeIf(it -> it.timestamp > cleanFrom);
        }
    }

    private static class SnapshotImpl extends Snapshot {
        private final Value[] values;
        private volatile long[] sorted;

        private SnapshotImpl(final Value[] values) {
            this.values = values;
        }

        @Override
        public double getValue(final double quantile) {
            if (values.length == 0) {
                return 0;
            }
            if (values.length == 1) {
                return values[0].value;
            }
            if (sorted == null) {
                synchronized (this) {
                    if (sorted == null) {
                        sorted = getValues();
                        Arrays.sort(sorted);
                    }
                }
            }
            return sorted[(int) Math.floor((sorted.length - 1) * quantile)];
        }

        @Override
        public long[] getValues() {
            return longs().toArray();
        }

        @Override
        public int size() {
            return values.length;
        }

        @Override
        public long getMax() {
            return longs().max().orElse(0);
        }

        @Override
        public double getMean() {
            return longs().sum() / (double) values.length;
        }

        @Override
        public long getMin() {
            return longs().min().orElse(0);
        }

        @Override
        public double getStdDev() {
            if (values.length <= 1) {
                return 0;
            }
            final double mean = getMean();
            return Math.sqrt(longs().map(v -> (long) Math.pow(v - mean, 2)).sum() / values.length - 1);
        }

        @Override
        public void dump(final OutputStream output) {
            longs().forEach(v -> {
                try {
                    output.write((v + "\n").getBytes(StandardCharsets.UTF_8));
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
            });
        }

        private LongStream longs() {
            return Stream.of(values).mapToLong(i -> i.value);
        }
    }

    private static final class Value {
        private final long timestamp;
        private final long value;

        private Value(final long timestamp, final long value) {
            this.timestamp = timestamp;
            this.value = value;
        }
    }
}
