/**
 **
 ** SyncCommand.java - Synchronized command execution controller for batch image processing
 **
 ** Copyright (C) 2024-2026 Elphel, Inc.
 **
 ** -----------------------------------------------------------------------------**
 **
 **  SyncCommand.java is free software: you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License as published by
 **  the Free Software Foundation, either version 3 of the License, or
 **  (at your option) any later version.
 **
 **  This program is distributed in the hope that it will be useful,
 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 **  GNU General Public License for more details.
 **
 **  You should have received a copy of the GNU General Public License
 **  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ** -----------------------------------------------------------------------------**
 **
 */
package com.elphel.imagej.correction;

import java.util.concurrent.atomic.AtomicInteger;

import com.elphel.imagej.common.GenericJTabbedDialog;

public class SyncCommand {
	public static final int STOP_NO =         0;
	public static final int STOP_ASAP =       1;
	public static final int STOP_CONVENIENT = 2;
	public boolean isRunning = false;
	public AtomicInteger stopRequested = new AtomicInteger(0); // 0 - not requested, 1 - ASAP, 2 - gracefully
	public String buttonLabel = "";
	public boolean confirm = true;
	public boolean fromMcp = false;
	// codex 2026-01-27: MCP-controlled pause/confirm
	private boolean mcpMode = false;
	private boolean confirmPending = false;
	private Boolean confirmDecision = null;
	private boolean confirmConvenient = false;
	private GenericJTabbedDialog confirmDialog = null;

	// codex 2026-01-27: enable MCP mode (non-GUI confirm)
	public void setMcpMode(boolean enabled) {
		this.mcpMode = enabled;
	}

	// codex 2026-01-27: request stop via MCP
	public boolean requestStop(boolean confirm, boolean asap) {
		this.confirm = confirm;
		this.stopRequested.set(asap ? STOP_ASAP : STOP_CONVENIENT);
		return true;
	}

	// codex 2026-01-27: confirm/cancel stop via MCP
	public boolean confirmStop(boolean stop) {
		synchronized (this) {
			if (!confirmPending) {
				return false;
			}
			confirmDecision = Boolean.valueOf(stop);
			confirmPending = false;
			if (confirmDialog != null) {
				confirmDialog.closeDialog();
				confirmDialog = null;
			}
			this.notifyAll();
		}
		return true;
	}

	public boolean isConfirmPending() {
		return confirmPending;
	}

	public boolean isConfirmConvenient() {
		return confirmConvenient;
	}
	
	public boolean interruptCommand() {
		boolean asap = false;
		GenericJTabbedDialog gd = new GenericJTabbedDialog("Interrupt Command",600,300);
		gd.addCheckbox ("Ask for confirmation",                              this.confirm,
				"If checked, program will pause at a checkpoint allowing to cancel the stop request and continue.");
		gd.addCheckbox ("ASAP",                                              asap,
				"Stop ASAP.  If uncheked, stop at more convenient stage.");
		gd.showDialog();
		if (gd.wasCanceled()) 
			return false;
		this.confirm=               gd.getNextBoolean();
		this.stopRequested.set(gd.getNextBoolean() ? STOP_ASAP : STOP_CONVENIENT );
		return true;
	}
	public boolean stopNow(boolean convenient) {
		if (stopRequested.get()==STOP_NO){
			return false;
		}
		//if (stopRequested.get() ==)
		if (!convenient && (stopRequested.get()==STOP_CONVENIENT)) {
			return false;
		}
		if (!confirm) {
			return true;
		}
		if (mcpMode) {
			synchronized (this) {
				confirmPending = true;
				confirmConvenient = convenient;
				confirmDecision = null;
				stopRequested.set(STOP_NO); // reset pending stop in any case.
				confirmDialog = new GenericJTabbedDialog(
						"Stop requested, " + (convenient ? "convenient point" : "ASAP point"), 600, 300, false);
				confirmDialog.addMessage("OK to stop, Cancel to continue");
				confirmDialog.setOnOk(new Runnable() {
					@Override
					public void run() {
						synchronized (SyncCommand.this) {
							confirmDecision = Boolean.TRUE;
							confirmPending = false;
							confirmDialog = null;
							SyncCommand.this.notifyAll();
						}
					}
				});
				confirmDialog.setOnCancel(new Runnable() {
					@Override
					public void run() {
						synchronized (SyncCommand.this) {
							confirmDecision = Boolean.FALSE;
							confirmPending = false;
							confirmDialog = null;
							SyncCommand.this.notifyAll();
						}
					}
				});
				confirmDialog.showDialogNonBlocking();
				while (confirmDecision == null) {
					try {
						this.wait();
					} catch (InterruptedException e) {
						Thread.currentThread().interrupt();
						confirmPending = false;
						if (confirmDialog != null) {
							confirmDialog.closeDialog();
							confirmDialog = null;
						}
						return false;
					}
				}
				return confirmDecision.booleanValue();
			}
		}
		GenericJTabbedDialog gd = new GenericJTabbedDialog("Stop requested, "+(convenient?"convenient point":"ASAP point"),600,300);
		gd.addMessage ("OK to stop, Cancel to continue");
		stopRequested.set(STOP_NO); // reset pending stop in any case.
		gd.showDialog();
		if (gd.wasCanceled()) 
			return false;
		return true;
	}
}
