package com.elphel.imagej.common;

import java.util.ArrayList;
import java.util.List;

import com.elphel.imagej.mcp.McpDialogField;
import com.elphel.imagej.mcp.McpDialogRegistry;
import com.elphel.imagej.mcp.McpDialogSession;

import ij.IJ;

public class GenericJTabbedDialogMcp extends GenericJTabbedDialog{
	// codex 2026-01-25: MCP dialog capture state
	private static boolean defaultMcpMode = false;
	private static long dialogTimeoutMs = 30000L;
	public boolean mcp_mode = false;
	private boolean mcpCanceled = false;
	private final List<McpDialogField> mcpFields = new ArrayList<McpDialogField>();
	private final String dialogTitle;
	private String currentTab = "";
	private int readIndex = 0;
	public GenericJTabbedDialogMcp(String title) {
		super(title);
		this.dialogTitle = title;
		this.mcp_mode = defaultMcpMode;
	}
	public GenericJTabbedDialogMcp(String title, int width, int height) {
		super(title, width, height);
		this.dialogTitle = title;
		this.mcp_mode = defaultMcpMode;
	}
	// codex 2026-01-27: allow modeless dialog creation
	public GenericJTabbedDialogMcp(String title, int width, int height, boolean modal) {
		super(title, width, height, modal);
		this.dialogTitle = title;
		this.mcp_mode = defaultMcpMode;
	}

	// codex 2026-01-25: global MCP mode default
	public static void setDefaultMcpMode(boolean enabled) {
		defaultMcpMode = enabled;
	}
	// codex 2026-01-27: expose MCP mode default
	public static boolean isDefaultMcpMode() {
		return defaultMcpMode;
	}
	// codex 2026-01-28: configurable MCP dialog submit timeout (0 = wait forever)
	public static void setDialogTimeoutMs(long timeoutMs) {
		dialogTimeoutMs = timeoutMs;
	}
	// codex 2026-01-28: override MCP mode per dialog instance
	public void setMcpMode(boolean enabled) {
		this.mcp_mode = enabled;
	}

	private void addMcpField(McpDialogField field) {
		mcpFields.add(field);
	}

	@Override
	public void addTab(String tab_name, String tab_tooltip) {
		if (mcp_mode) {
			// codex 2026-01-25: capture current tab for MCP schema
			currentTab = tab_name;
		}
		else super.addTab(tab_name, tab_tooltip);
	}

	@Override
	public void addCheckbox(String label, boolean defaultValue, String tooltip) {
		if (mcp_mode) {
			addMcpField(new McpDialogField(
					McpDialogField.Type.BOOLEAN,
					label,
					tooltip,
					currentTab,
					null,
					null,
					Boolean.toString(defaultValue)));
		}
		else super.addCheckbox(label, defaultValue, tooltip);
	}

	@Override
	public void addNumericField(String label, double defaultValue, int digits, int columns, String units, String tooltip) {
		if (mcp_mode) {
			String defaultText = IJ.d2s(defaultValue, digits);
			addMcpField(new McpDialogField(
					McpDialogField.Type.NUMBER,
					label,
					tooltip,
					currentTab,
					units,
					null,
					defaultText));
		}
		else super.addNumericField(label, defaultValue, digits, columns, units, tooltip);
	}    

	@Override
	public void addStringField (
			String label,
			String value,
			int    width,
			String tooltip) {
		if (mcp_mode) {
			addMcpField(new McpDialogField(
					McpDialogField.Type.STRING,
					label,
					tooltip,
					currentTab,
					null,
					null,
					value));
		}
		else super.addStringField (label, value, width, tooltip);
	}

	@Override
	public void addChoice(String label, String[] items, String defaultItem, String tooltip, int count) {
		if (mcp_mode) {
			addMcpField(new McpDialogField(
					McpDialogField.Type.CHOICE,
					label,
					tooltip,
					currentTab,
					null,
					items,
					defaultItem));
		}
		else super.addChoice(label, items, defaultItem, tooltip, count);
	}	

	@Override
	public void addChoice(String label, String[] items, String defaultItem) {
		addChoice(label, items, defaultItem, null, 0);
	}

	@Override
	public void addChoice(String label, String[] items, String defaultItem, String tooltip) {
		addChoice(label, items, defaultItem, tooltip, 0);
	}

	@Override
	public void addDefaultButtons() { // not used
		if (mcp_mode) {

		}
		else super.addDefaultButtons();
	}

	@Override
	public void addMessage(String message, String tooltip) {
		if (mcp_mode) {
			addMcpField(new McpDialogField(
					McpDialogField.Type.MESSAGE,
					message,
					tooltip,
					currentTab,
					null,
					null,
					null));
		}
		else super.addMessage(message, tooltip);
	}

	@Override
	public void buildDialog() { // non-blocking, does not show
		if (mcp_mode) {
			// codex 2026-01-25: publish dialog schema to MCP registry
			readIndex = 0;
			boolean applied = McpDialogRegistry.setCurrent(new McpDialogSession(dialogTitle, mcpFields));
			if (!applied) {
				System.out.println("MCP: dialog already active, ignoring \"" + dialogTitle + "\"");
			}
		}
		else super.buildDialog();
	}

	private McpDialogField nextField(McpDialogField.Type type) {
		while (readIndex < mcpFields.size()
				&& mcpFields.get(readIndex).type == McpDialogField.Type.MESSAGE) {
			readIndex++;
		}
		if (readIndex >= mcpFields.size()) {
			return null;
		}
		McpDialogField field = mcpFields.get(readIndex);
		if (field.type != type) {
			throw new IllegalArgumentException(
					"MCP dialog field mismatch: expected " + type + ", got " + field.type + " label=" + field.label);
		}
		readIndex++;
		return field;
	}

	private String getValueOrDefault(McpDialogField field) {
		McpDialogSession session = McpDialogRegistry.getCurrent();
		if (session != null && field != null) {
			String value = session.getValue(field.label);
			if (value != null) {
				return value;
			}
		}
		return field == null ? null : field.defaultValue;
	}

	@Override
	public boolean getNextBoolean() {
		if (mcp_mode) {
			McpDialogField field = nextField(McpDialogField.Type.BOOLEAN);
			String value = getValueOrDefault(field);
			if (value == null) {
				return false;
			}
			String normalized = value.trim().toLowerCase();
			return normalized.equals("true") || normalized.equals("1") || normalized.equals("yes") || normalized.equals("y");
		}
		else return super.getNextBoolean();
	}

	@Override
	public int getNextChoiceIndex() {
		if (mcp_mode) {
			McpDialogField field = nextField(McpDialogField.Type.CHOICE);
			String value = getValueOrDefault(field);
			if (value == null || field.choices == null) {
				return 0;
			}
			try {
				int idx = Integer.parseInt(value.trim());
				if (idx >= 0 && idx < field.choices.length) {
					return idx;
				}
			} catch (NumberFormatException e) {
				// ignore and try by name
			}
			for (int i = 0; i < field.choices.length; i++) {
				if (field.choices[i].equals(value)) {
					return i;
				}
			}
			return 0;
		}
		else return super.getNextChoiceIndex();
	}

	@Override
	public double getNextNumber() {
		if (mcp_mode) {
			McpDialogField field = nextField(McpDialogField.Type.NUMBER);
			String value = getValueOrDefault(field);
			if (value == null || value.isEmpty()) {
				return Double.NaN;
			}
			try {
				return Double.parseDouble(value);
			} catch (NumberFormatException e) {
				return Double.NaN;
			}
		}
		else return super.getNextNumber();
	}

	@Override
	public String getNextString() {
		if (mcp_mode) {
			McpDialogField field = nextField(McpDialogField.Type.STRING);
			String value = getValueOrDefault(field);
			return value == null ? "" : value;
		}
		else return super.getNextString();
	}

	@Override
	public boolean showDialog() {
		if (mcp_mode) {
			buildDialog();
			McpDialogSession session = McpDialogRegistry.getCurrent();
			if (session != null) {
				long timeout = dialogTimeoutMs;
				Boolean ok = (timeout <= 0) ? session.awaitSubmit(Long.MAX_VALUE) : session.awaitSubmit(timeout);
				if (ok != null && !ok.booleanValue()) {
					mcpCanceled = true;
				} else {
					mcpCanceled = false;
				}
			}
			McpDialogRegistry.setCurrent(null);
			return true;
		}
		else return super.showDialog();
	}

	// codex 2026-01-27: modeless dialog for GUI mode
	public void showDialogNonBlocking() {
		if (mcp_mode) {
			buildDialog();
		}
		else super.showDialogNonBlocking();
	}

	@Override
	public String showDialogAny() {
		if (mcp_mode) {
			buildDialog();
			return "";
		}
		else return super.showDialogAny();
	}


	@Override
	public boolean wasCanceled() {
		if (mcp_mode) {
			return mcpCanceled;
		}
		else return super.wasCanceled();
	}

	@Override
	public boolean wasOKed() {
		if (mcp_mode) {
			return true;
		}
		else return super.wasOKed();
	}
}
