package com.android.commands.monkey.ape.jev;

import java.util.*;
import org.json.*;

/** Bounded function-duration samples; nested segments are reported separately, never summed. */
public final class JevTiming {
    private static final int LIMIT=2048;
    private static final class Samples {
        long count,total,max;final long[] values=new long[LIMIT];
        void add(long ns){values[(int)(count++%LIMIT)]=ns;total+=ns;max=Math.max(max,ns);}
    }
    private final java.util.concurrent.locks.ReentrantLock budgetLock=new java.util.concurrent.locks.ReentrantLock();
    private final Map<String,Samples> durations=new TreeMap<String,Samples>();
    private final Map<String,Long> counts=new TreeMap<String,Long>();
    public void record(String segment,long nanos) {JevDeadline.lock(budgetLock);try {
        Samples s=durations.get(segment);if(s==null){s=new Samples();durations.put(segment,s);}s.add(Math.max(0,nanos));
    } finally {budgetLock.unlock();}}
    public void count(String name,long amount){JevDeadline.lock(budgetLock);try {Long n=counts.get(name);counts.put(name,(n==null?0:n)+amount);} finally {budgetLock.unlock();}}
    public void reset(){JevDeadline.lock(budgetLock);try {durations.clear();counts.clear();} finally {budgetLock.unlock();}}
    public JSONObject snapshot() {JevDeadline.lock(budgetLock);try {
        JSONObject out=new JSONObject(),timings=new JSONObject();
        try {
            for(Map.Entry<String,Samples> entry:durations.entrySet()) {
                Samples s=entry.getValue();long[] sorted=Arrays.copyOf(s.values,(int)Math.min(s.count,LIMIT));Arrays.sort(sorted);
                timings.put(entry.getKey(),JevRegistry.fields("count",s.count,"total_ns",s.total,"max_ns",s.max,
                    "sample_count",sorted.length,"p50_ns",sorted[(sorted.length-1)/2],"p95_ns",sorted[(int)Math.ceil(sorted.length*.95)-1]));
            }
            out.put("durations",timings).put("counts",new JSONObject(counts)).put("sample_policy","last-2048; nested segments must not be summed");
        } catch(JSONException e){throw new IllegalStateException(e);}return out;
    } finally {budgetLock.unlock();}}
}
