const ZinTest = function(runner, jbm) {
	this.logger = runner.logger;
	this.jbm = jbm;
	this.logger.log("creating ZinTest with ", runner, jbm);
}
ZinTest.prototype.data = function(cx, zn, fl) {
	zn = cx.full(zn);
	fl = cx.full(fl);
	this.jbm.data(cx, zn, fl);
}
ZinTest.prototype.user = function(cx, zn, u) {
	zn = cx.full(zn);
	u = cx.full(u);
	this.jbm.user(cx, zn, u);
}
ZinTest.prototype.dump = function(cx, zn) {
	zn = cx.full(zn);
	this.jbm.dump(cx, zn);
}
ZinTest.prototype.attach = function(cx, zn, u) {
	zn = cx.full(zn);
	u = cx.full(u);
	this.jbm.attach(cx, zn, u);
}
ZinTest.prototype.hasBench = function(cx, zn, aid, bench) {
	zn = cx.full(zn);
	aid = cx.full(aid);
	bench = cx.full(bench);
	this.jbm.hasBench(cx, zn, aid, bench);
}
ZinTest.prototype.hasEntityLink = function(cx, zn, bid, eid) {
	zn = cx.full(zn);
	bid = cx.full(bid);
	eid = cx.full(eid);
	this.jbm.hasEntityLink(cx, zn, bid, eid);
}
ZinTest.prototype.obtainDataEntry = function(cx, zn, ziid, ty, iv) {
	zn = cx.full(zn);
	ziid = cx.full(ziid);
	ty = cx.full(ty);
	var self = this;
	this.jbm.obtainDataEntry(cx, zn, ziid, ty, { result: function(s) {
		self.logger.log("have obtained ", s);
		var jp = JSON.parse(s);
		self.logger.log("parsed as ", jp);
		var trav = new ListTraverser(cx, new CollectingState(cx));
		var jb = new JsonBeachhead(cx, null, null, null);
		try {
			jb.handleArg(trav, cx, jp);
			self.logger.log("concluded with", trav.ret[0]);
			iv.bindActual(trav.ret[0]);	
		} catch (e) {
			self.logger.log("error was", e);
			self.logger.log("error at", e.stack);
		}
	}});
}
ZinTest.prototype.obtainPersona = function(cx, zn, arena, bench, identity, ty, iv) {
	zn = cx.full(zn);
	arena = cx.full(arena);
	bench = cx.full(bench);
	identity = cx.full(identity);
	ty = cx.full(ty);
	var self = this;
	this.jbm.obtainPersona(cx, zn, arena, bench, identity, ty, { result: function(s) {
		self.logger.log("have obtained persona json ", s);
		var jp = JSON.parse(s);
		self.logger.log("parsed as ", jp);
		var trav = new ListTraverser(cx, new CollectingState(cx));
		var jb = new JsonBeachhead(cx, null, null, null);
		try {
			jb.handleArg(trav, jp);
			self.logger.log("concluded with", trav.ret[0]);
			iv.bindActual(trav.ret[0]);	
		} catch (e) {
			self.logger.log("error was", e);
			self.logger.log("error at", e.stack);
		}
	}});
}

const ZinTestModule = function(bridge, conn) {
	this.bridge = bridge;
	this.conn = conn;
	this.servers = {};
}

ZinTestModule.prototype.data = function(cx, zn, fl) {
	var self = this;
	this.bridge.lock("zin.data");
	this.bridge.send({action: "data", conn: this.conn, requestId: this.bridge.nextRequestId(() => self.bridge.unlock("zin.data")), args: [ zn, fl ]});
}

ZinTestModule.prototype.user = function(cx, zn, u) {
	var self = this;
	this.bridge.lock("zin.data");
	this.bridge.send({action: "user", conn: this.conn, requestId: this.bridge.nextRequestId(() => self.bridge.unlock("zin.data")), args: [ zn, u ]});
}

ZinTestModule.prototype.attach = function(cx, zn, u) {
	var self = this;
	this.bridge.lock("zin.data");
	this.bridge.onUnlock(() => self.ensureServer(zn, u));
	this.bridge.send({action: "attach", conn: this.conn, requestId: this.bridge.nextRequestId(() => self.bridge.unlock("zin.data")), args: [ zn, u ]});
}

ZinTestModule.prototype.obtainDataEntry = function(cx, zn, ziid, ty, ih) {
	var self = this;
	this.bridge.lock("zin.obtainDataEntry");
	var onResponse = (msg) => {
		ih.result(msg.value);
		self.bridge.unlock("zin.obtainDataEntry");
	};
	this.bridge.send({action: "obtainDataEntry", conn: this.conn, requestId: this.bridge.nextRequestId(onResponse), args: [ zn, ziid, ty, ih ]});
}

ZinTestModule.prototype.ensureServer = function(zn, u) {
	if (!this.servers[zn]) {
		this.servers[zn] = this.bridge.runner.broker.connectToServer("ws://" + zn + ":18080/wsapi/tok_" + u + "/secret_" + u);
	}
	var srv = this.servers[zn];
	var max = 10;
	var unl = () => {
		console.log("checking if", srv.conn, "is connected yet");
		if (srv.conn != null && srv.conn.readyState ==1)
			this.bridge.unlock("connected ziwsh");
		else if (--max > 0)
			setTimeout(unl, 100);
		else
			console.log("never connected");
	};
	unl();
}

//--EXPORT
/* istanbul ignore else */ 
if (typeof(module) !== 'undefined') {
	module.exports = ZinTest;
} else {
//--WINDOW
	window.ZinTest = ZinTest;
	window.ZinTestModule = ZinTestModule;
	window.UTRunner.modules['org.ziniki.storage.memory.ZinikiTestModule'] = ZinTest;
}