package hh.dejsem.net;

import hh.dejsem.K;
import hh.lib.D;

public enum SrvCmd {
	/**
	 * synchronous actions on cmd connection to server executed in separate thread
	 * <p>
	 * ● actions are initiated via execute().get(), i.e. blocking
	 * <p>
	 * ● actions should be short time, immediate
	 * <p>
	 * ● after action (or batch of actions) cmd connection needs to be closed
	 * <p>
	 * ● connection close is up to caller (to be able to do actions in batch)
	 * <p>
	 * ● SETPEER operates first on peer connection (binds to port) and then sends ip:port to server
	 */

	CLOSE("CLOSE___") {         // close connection on command port
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.connClose();
			return null;
		}
	},

	CREATEDIR("CREATDIR") {     // create directory
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.createDir((String) parms[0]);
			return null;
		}
	},

	DELETE("DELETE__") {        // recursively delete object
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.delete((String) parms[0]);
			return null;
		}
	},

	EXPOSE("EXPOSE__") {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.expose((String) parms[0]);
		}
	},

	FREE("FREE____") {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.getFreeSpace();
		}
	},

	GETPEER("GETPEER_") {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.getPeerHost();
		}
	},

	HIDE("HIDE____") {
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.hide((String) parms[0]);
			return null;
		}
	},

	MOVE("MOVE____") {
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.move((String) parms[0], (String) parms[1]);
			return null;
		}
	},

	LONGTASK {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.longtask();
		}
	},

	PULLCLIP {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.pullClip((String) parms[0]);
		}
	},

	PULLHIST {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.pullHistList();
//			return null;
		}
	},

	PULLLIST {
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.pullListSrv((String) parms[0], (String) parms[1]);
			return null;
		}
	},

	PUSHCLIP {
		@Override
		public Object action(Object... parms) throws Exception {
			K.cmdConn.pushClip((NetData)parms[0]);
			return null;
		}
	},
	RECKON("RECKON__") {
		@Override
		public Object action(Object... parms) throws Exception {
			return K.cmdConn.reckon((String) parms[0]);
		}
	},

	SETPEER("SETPEER_") {   // atavismus z doby před použitím UDP
		@Override
		public Object action(Object... parms) throws Exception {
			((NetConnPeer)parms[0]).bindSockToPeer();
			return null;
		}
	};

	D d;
	final String cmd;

	SrvCmd() {
		this.cmd = name();
	}

	SrvCmd(String cmd) {
		this.cmd = cmd;
	}

	public abstract Object action(Object... args) throws Exception;

	public Object exec(D d, Object parm) throws Exception {
		return exec(d, new Object[]{parm});
	}

	public Object exec(D d, Object[] parms) throws Exception {
		this.d = d.klon(this);
		SrvCmdThread t = new SrvCmdThread(d, this, parms);
		t.start();
		t.join();
		if (t.exception == null) return t.result;
		else throw t.exception;
	}

	static class SrvCmdThread extends Thread {
		D d;
		public SrvCmd action;
		public Object[] args;
		public Object result;
		public Exception exception = null;

		public SrvCmdThread(D d, SrvCmd action, Object[] args) {
			this.d = d.klon(this);
			this.action = action;
			this.args = args;
		}

		public void run() {
			try {
				if (K.netNode == null) K.netNode = new NetNode(d);
				if (K.cmdConn == null) K.cmdConn = new NetConnSrv(d);    // cmd conn to server
				if (d.ll(2)) d.l("--->action=" + action);
				result = action.action(args);
			} catch (Exception e) { this.exception = e; }
		}
	}
}

