/*=============================================================================#
 # Copyright (c) 2009, 2019 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.rj.servi;

import java.io.File;
import java.rmi.RemoteException;

import org.eclipse.statet.jcommons.rmi.RMIAddress;

import org.eclipse.statet.internal.rj.servi.server.RServiBackend;
import org.eclipse.statet.rj.RjException;
import org.eclipse.statet.rj.servi.node.RServiNode;


public abstract class NodeHandler {
	
	
	protected RServiNode node;
	
	RMIAddress address;
	File dir;
	Process process;
	
	private String clientLabel;
	private RServiBackend clientHandler;
	
	boolean isConsoleEnabled;
	
	private final long startTime;
	private long shutdownTime;
	
	
	public NodeHandler() {
		this.startTime= System.currentTimeMillis();
		this.shutdownTime= -1;
	}
	
	
	public boolean isConsoleEnabled() {
		return this.isConsoleEnabled;
	}
	
	public void enableConsole(final String authConfig) throws RjException {
		try {
			this.isConsoleEnabled= this.node.setConsole(authConfig);
		}
		catch (final Exception e) {
			Utils.logError("An error occurred when configuring the debug console.", e);
			throw new RjException("An error occurred when configuring the debug console. See server log for detail.");
		}
	}
	
	public void disableConsole() throws RjException {
		enableConsole(null);
	}
	
	public RMIAddress getAddress() {
		return this.address;
	}
	
	
	void init(final RServiNode node, final Process process) {
		this.node= node;
		this.process= process;
	}
	
	void bindClient(final String name, final String host) throws RemoteException {
		final StringBuilder sb= new StringBuilder(80);
		if (name != null) {
			sb.append(name);
		}
		sb.append('@');
		sb.append(host);
		final String client= sb.toString();
		this.clientHandler= this.node.bindClient(client);
		setClientLabel(client);
	}
	
	void unbindClient() throws RemoteException {
		this.clientHandler= null;
		setClientLabel(null);
		this.node.unbindClient();
	}
	
	void shutdown() throws RemoteException {
		this.shutdownTime= System.currentTimeMillis();
		this.clientHandler= null;
		setClientLabel(null);
		final RServiNode node= this.node;
		this.node= null;
		if (node != null) {
			node.shutdown();
		}
	}
	
	RServiBackend getClientHandler() {
		return this.clientHandler;
	}
	
	void setClientLabel(final String clientLabel) {
		this.clientLabel= clientLabel;
	}
	
	public String getClientLabel() {
		return this.clientLabel;
	}
	
	public long getStartTime() {
		return this.startTime;
	}
	
	public long getShutdownTime() {
		return this.shutdownTime;
	}
	
}
