/* ###
 * IP: GHIDRA
 *
 * Licensed 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 ghidra.app.plugin.core.debug.gui.tracecalltree;

import ghidra.app.events.CloseProgramPluginEvent;
import ghidra.app.events.OpenProgramPluginEvent;
import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.core.debug.AbstractDebuggerPlugin;
import ghidra.app.plugin.core.debug.DebuggerPluginPackage;
import ghidra.app.plugin.core.debug.event.TraceActivatedPluginEvent;
import ghidra.app.plugin.core.debug.event.TraceClosedPluginEvent;
import ghidra.app.services.*;
import ghidra.debug.api.tracemgr.DebuggerCoordinates;
import ghidra.framework.plugintool.*;
import ghidra.framework.plugintool.util.PluginStatus;
import ghidra.trace.model.Trace;

@PluginInfo(
	shortDescription = "Call Tree Viewer For Traces",
	description = "Displays a call tree of all functions ran in a trace",
	category = PluginCategoryNames.DEBUGGER,
	packageName = DebuggerPluginPackage.NAME,
	status = PluginStatus.UNSTABLE,
	servicesRequired = { DebuggerTraceManagerService.class, DebuggerStaticMappingService.class,
		DebuggerListingService.class, ProgressService.class },
	eventsConsumed = { TraceClosedPluginEvent.class, TraceActivatedPluginEvent.class,
		OpenProgramPluginEvent.class, CloseProgramPluginEvent.class }
)
public class TraceCallTreePlugin extends AbstractDebuggerPlugin {
	TraceCallTreeProvider provider;

	private DebuggerCoordinates current;

	public TraceCallTreePlugin(PluginTool tool) {
		super(tool);
	}

	@Override
	protected void dispose() {
		tool.removeComponentProvider(provider);
		provider.dispose();
		super.dispose();
	}

	@Override
	protected void init() {
		super.init();
		provider = new TraceCallTreeProvider(this);
	}

	@Override
	public void processEvent(PluginEvent event) {
		super.processEvent(event);
		switch (event) {
			case final TraceClosedPluginEvent evt -> {
				final Trace t = evt.getTrace();
				if ((current != null) && (current.getTrace() == t)) {
					current = null;
					provider.setCoordinates(null);
				}
				provider.traceClosed(evt.getTrace());
			}
			case final TraceActivatedPluginEvent evt -> {
				current = evt.getActiveCoordinates();
				provider.setCoordinates(current);
			}
			case final OpenProgramPluginEvent evt -> {
				provider.programOpened(evt.getProgram());
			}
			case final CloseProgramPluginEvent evt -> {
				provider.programClosed(evt.getProgram());
			}
			default -> {
			}
		}
	}
}
