package org.gridkit.jvmtool.stacktrace.codec.json;

import org.gridkit.jvmtool.codec.stacktrace.ThreadSnapshotEventPojo;
import org.gridkit.jvmtool.event.GenericEvent;
import org.gridkit.jvmtool.jvmevents.JvmEvents;
import org.gridkit.jvmtool.stacktrace.StackFrameArray;
import org.gridkit.jvmtool.stacktrace.StackFrameList;
import org.gridkit.jvmtool.stacktrace.codec.json.JsonStreamHandler.JsonEntityHandler;
import org.gridkit.jvmtool.stacktrace.codec.json.JsonStreamHandler.JsonObjectHandler;

class JfrExecutionSampleHandler implements JsonObjectHandler {

    public static final String TYPE_ID = "jdk.ExecutionSample";

    private final JfrEventParser parser;
    private GenericEvent event = new GenericEvent();
    private StackFrameList threadTrace;

    private ThreadInfoHandler threadInfo = new ThreadInfoHandler() {

        @Override
        protected void onComplete() {
            if (this.javaName != null) {
                event.tags().put(JvmEvents.THREAD_NAME, this.javaName);
            }
            if (this.javaThreadId > 0) {
                event.counters().set(JvmEvents.THREAD_ID, this.javaThreadId);
            }
        }
    };

    private StackTraceHandler stackTrace = new StackTraceHandler() {

        @Override
        protected void onComplete() {
            threadTrace = new StackFrameArray(frames);
        }
    };

    public JfrExecutionSampleHandler(JfrEventParser parser) {
        this.parser = parser;
    }

    @Override
    public void onScalarFieldValue(String fieldName, Object val) {
        if ("startTime".equals(fieldName)) {
            JfrHelper.setTimestamp(event, val);
        }
        else if ("state".equals(fieldName)) {
            JfrHelper.setThreadState(event, val);
        }
    }

    @Override
    public JsonEntityHandler onEntityField(String fieldName) {
        if ("sampledThread".equals(fieldName)) {
            return threadInfo;
        }
        else if ("stackTrace".equals(fieldName)) {
            return stackTrace;
        }
        else {
            return JsonStreamHandler.NULL_HANDLER;
        }
    }

    @Override
    public void onObjectComplete() {
        event.tags().put("jfr.typeId", TYPE_ID);
        ThreadSnapshotEventPojo cevent = new ThreadSnapshotEventPojo();
        cevent.loadFromRawEvent(event);
        cevent.stackTrace(threadTrace);
        parser.push(cevent);
        event = new GenericEvent();
    }
}
