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

import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonMap;
import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;

import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;

import org.apache.geronimo.microprofile.metrics.common.prometheus.PrometheusFormatter;
import org.eclipse.microprofile.metrics.ConcurrentGauge;
import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.Histogram;
import org.eclipse.microprofile.metrics.Metadata;
import org.eclipse.microprofile.metrics.Meter;
import org.eclipse.microprofile.metrics.Metered;
import org.eclipse.microprofile.metrics.Metric;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.Snapshot;
import org.eclipse.microprofile.metrics.Timer;

@Path("metrics")
public class MetricsEndpoints {
    private MetricRegistry baseRegistry;
    private MetricRegistry vendorRegistry;
    private MetricRegistry applicationRegistry;

    private SecurityValidator securityValidator = new SecurityValidator() {
        {
            init();
        }
    };

    private PrometheusFormatter prometheus = new PrometheusFormatter().enableOverriding();

    public void setBaseRegistry(final MetricRegistry baseRegistry) {
        this.baseRegistry = baseRegistry;
    }

    public void setVendorRegistry(final MetricRegistry vendorRegistry) {
        this.vendorRegistry = vendorRegistry;
    }

    public void setApplicationRegistry(final MetricRegistry applicationRegistry) {
        this.applicationRegistry = applicationRegistry;
    }

    public void setSecurityValidator(final SecurityValidator securityValidator) {
        this.securityValidator = securityValidator;
    }

    public void setPrometheus(final PrometheusFormatter prometheus) {
        this.prometheus = prometheus;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Object getJson(@Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return Stream.of(MetricRegistry.Type.values())
                .collect(toMap(MetricRegistry.Type::getName, it -> findRegistry(it.getName()).getMetrics().entrySet().stream()
                        .collect(toMap(this::getKey, m -> toJson(map(m.getValue()), formatTags(m.getKey())), (a, b) -> a))));
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getText(@Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return Stream.of(MetricRegistry.Type.values())
                .map(type -> {
                    final MetricRegistry metricRegistry = findRegistry(type.getName());
                    return prometheus.toText(metricRegistry, type.getName(), metrics(metricRegistry));
                })
                .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                .toString();
    }

    @GET
    @Path("{registry}")
    @Produces(MediaType.APPLICATION_JSON)
    public Object getJson(@PathParam("registry") final String registry,
                          @Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return findRegistry(registry).getMetrics().entrySet().stream()
                .collect(toMap(this::getKey, it -> toJson(map(it.getValue()), formatTags(it.getKey())), (a, b) -> a));
    }

    @GET
    @Path("{registry}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getText(@PathParam("registry") final String registry,
                          @Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        final MetricRegistry metricRegistry = findRegistry(registry);
        return prometheus.toText(metricRegistry, registry, metrics(metricRegistry)).toString();
    }

    @GET
    @Path("{registry}/{metric}")
    @Produces(MediaType.APPLICATION_JSON)
    public Object getJson(@PathParam("registry") final String registry,
                          @PathParam("metric") final String name,
                          @Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return singleEntry(name, findRegistry(registry), this::map);
    }

    @GET
    @Path("{registry}/{metric}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getText(@PathParam("registry") final String registry,
                          @PathParam("metric") final String name,
                          @Context final SecurityContext securityContext,
                          @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        final MetricRegistry metricRegistry = findRegistry(registry);
        return prometheus.toText(
                metricRegistry, registry,
                singleEntry(name, metricRegistry, identity())).toString();
    }

    @OPTIONS
    @Path("{registry}/{metric}")
    @Produces(MediaType.APPLICATION_JSON)
    public Object getMetadata(@PathParam("registry") final String registry,
                              @PathParam("metric") final String name,
                              @Context final SecurityContext securityContext,
                              @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return ofNullable(findRegistry(registry).getMetadata().get(name))
                .map(metric -> singletonMap(name, mapMeta(metric, new MetricID(name))))
                .orElse(emptyMap());
    }

    @OPTIONS
    @Path("{registry}")
    @Produces(MediaType.APPLICATION_JSON)
    public Object getMetadata(@PathParam("registry") final String registry,
                              @Context final SecurityContext securityContext,
                              @Context final UriInfo uriInfo) {
        securityValidator.checkSecurity(securityContext, uriInfo);
        return findRegistry(registry).getMetadata().entrySet().stream()
                .collect(toMap(Map.Entry::getKey, e -> mapMeta(e.getValue(), new MetricID(e.getKey())), (a, b) -> a));
    }

    private Map<String, Metric> metrics(final MetricRegistry metricRegistry) {
        return metricRegistry.getMetrics().entrySet().stream()
                .collect(toMap(this::getKey, Map.Entry::getValue, (a, b) -> a));
    }

    private <T> Map<String, T> singleEntry(final String id, final MetricRegistry metricRegistry,
                                           final Function<Metric, T> metricMapper) {
        return ofNullable(metricRegistry.getMetrics().get(new MetricID(id)))
                .map(metric -> singletonMap(id, metricMapper.apply(metric)))
                .orElseGet(Collections::emptyMap);
    }

    private Meta mapMeta(final Metadata value, final MetricID metricID) {
        return ofNullable(value).map(v -> new Meta(value, metricID)).orElse(null);
    }

    private Object map(final Metric metric) {
        if (Counter.class.isInstance(metric)) {
            return Counter.class.cast(metric).getCount();
        }
        if (Gauge.class.isInstance(metric)) {
            return Gauge.class.cast(metric).getValue();
        }
        return metric;
    }

    private String getKey(final Map.Entry<MetricID, Metric> e) {
        if (Counter.class.isInstance(e.getValue()) || Gauge.class.isInstance(e.getValue())) {
            return e.getKey().getName() + formatTags(e.getKey());
        }
        return e.getKey().getName();
    }

    // https://github.com/eclipse/microprofile-metrics/issues/508
    private Object toJson(final Object metric, final String nameSuffix) {
        if (Timer.class.isInstance(metric)) {
            final Timer meter = Timer.class.cast(metric);
            final Map<Object, Object> map = new HashMap<>(15);
            map.putAll(snapshot(meter.getSnapshot(), nameSuffix));
            map.putAll(meter(meter, nameSuffix));
            return map;
        }
        if (Meter.class.isInstance(metric)) {
            return meter(Meter.class.cast(metric), nameSuffix);
        }
        if (Histogram.class.isInstance(metric)) {
            final Histogram histogram = Histogram.class.cast(metric);
            final Map<Object, Object> map = new HashMap<>(11);
            map.putAll(snapshot(histogram.getSnapshot(), nameSuffix));
            map.put("count" + nameSuffix, histogram.getCount());
            return map;
        }
        if (ConcurrentGauge.class.isInstance(metric)) {
            final ConcurrentGauge concurrentGauge = ConcurrentGauge.class.cast(metric);
            final Map<Object, Object> map = new HashMap<>(3);
            map.put("min" + nameSuffix, concurrentGauge.getMin());
            map.put("current" + nameSuffix, concurrentGauge.getCount());
            map.put("max" + nameSuffix, concurrentGauge.getMax());
            return map;
        }
        // counters and gauges are unwrapped so skip it
        return metric;
    }

    private Map<String, Object> meter(final Metered metered, final String nameSuffix) {
        final Map<String, Object> map = new HashMap<>(5);
        map.put("count" + nameSuffix, metered.getCount());
        map.put("meanRate" + nameSuffix, metered.getMeanRate());
        map.put("oneMinRate" + nameSuffix, metered.getOneMinuteRate());
        map.put("fiveMinRate" + nameSuffix, metered.getFiveMinuteRate());
        map.put("fifteenMinRate" + nameSuffix, metered.getFifteenMinuteRate());
        return map;
    }

    private Map<String, Object> snapshot(final Snapshot snapshot, final String nameSuffix) {
        final Map<String, Object> map = new HashMap<>(10);
        map.put("p50" + nameSuffix, snapshot.getMedian());
        map.put("p75" + nameSuffix, snapshot.get75thPercentile());
        map.put("p95" + nameSuffix, snapshot.get95thPercentile());
        map.put("p98" + nameSuffix, snapshot.get98thPercentile());
        map.put("p99" + nameSuffix, snapshot.get99thPercentile());
        map.put("p999" + nameSuffix, snapshot.get999thPercentile());
        map.put("min" + nameSuffix, snapshot.getMin());
        map.put("mean" + nameSuffix, snapshot.getMean());
        map.put("max" + nameSuffix, snapshot.getMax());
        map.put("stddev" + nameSuffix, snapshot.getStdDev());
        return map;
    }

    private MetricRegistry findRegistry(final String registry) {
        switch (Stream.of(MetricRegistry.Type.values()).filter(it -> it.getName().equals(registry)).findFirst()
                .orElseThrow(() -> new WebApplicationException(Response.Status.NOT_FOUND))) {
            case BASE:
                return baseRegistry;
            case VENDOR:
                return vendorRegistry;
            default:
                return applicationRegistry;
        }
    }

    private String formatTags(final MetricID id) {
        return id.getTags().isEmpty() ? "" : (';' + id.getTags().entrySet().stream()
                .map(e -> e.getKey() + "=" + e.getValue())
                .collect(joining(",")));
    }

    public static class Meta {
        private final Metadata value;
        private final MetricID metricID;

        private Meta(final Metadata value, final MetricID metricID) {
            this.value = value;
            this.metricID = metricID;
        }

        public String getName() {
            return value.getName();
        }

        public String getDisplayName() {
            return value.getDisplayName();
        }

        public String getDescription() {
            return value.getDescription().orElse(null);
        }

        public String getType() {
            return value.getType();
        }

        public String getTypeRaw() {
            return value.getTypeRaw().name();
        }

        public String getUnit() {
            return value.getUnit().orElse(null);
        }

        public boolean isReusable() {
            return value.isReusable();
        }

        public String getTags() { // not sure why tck expect it, sounds worse than native getTags for clients
            return metricID.getTags().entrySet().stream().map(e -> e.getKey() + '=' + e.getValue()).collect(joining(","));
        }
    }
}
