#include "vxi11.h"

#define	VXI11_DEFAULT_TIMEOUT	1000

static CLIENT* clnt = NULL;
static Device_Link link;

int vxi11_open(char* address, char* device) {
	clnt = clnt_create(address, DEVICE_CORE, DEVICE_CORE_VERSION, "tcp");
	if (clnt == NULL) {
		return 0;
	}
	else {
		Create_LinkParms link_parms;
		link_parms.clientId = (long) clnt;
		link_parms.lockDevice = 0;
		link_parms.lock_timeout = VXI11_DEFAULT_TIMEOUT;
		link_parms.device = device;

		Create_LinkResp* linkresp = create_link_1(&link_parms, clnt);
		if (linkresp != NULL && linkresp->error == 0) {
			link = linkresp->lid;
			return 1;
		}
		else if (linkresp == NULL)
			return 0;
		else
			return -(linkresp->error);
	}
}

int vxi11_readstatusbyte() {
	if (clnt == NULL)
		return;
	Device_GenericParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout =
			VXI11_DEFAULT_TIMEOUT };
	Device_ReadStbResp* resp = device_readstb_1(&params, clnt);

	if (resp != NULL && resp->error == 0)
		return resp->stb;
	else if (resp == NULL)
		return 0;
	else
		return -1;
}

int vxi11_write(char* data, unsigned int len) {
	if (clnt == NULL) {
		return;
	}

	Device_WriteParms params = { .lid = link, .io_timeout = VXI11_DEFAULT_TIMEOUT,
			.lock_timeout = VXI11_DEFAULT_TIMEOUT, .flags = 0x0 };
	params.data.data_len = len;
	params.data.data_val = data;

	Device_WriteResp* resp = device_write_1(&params, clnt);
	if (resp != NULL && resp->error == 0)
		return resp->size;
	else if (resp == NULL)
		return 0;
	else
		return -1;
}

int vxi11_read() {
	if (clnt == NULL) {
		return;
	}

	Device_ReadParms params = { .lid = link, .requestSize = 256, .io_timeout = VXI11_DEFAULT_TIMEOUT, .lock_timeout =
			VXI11_DEFAULT_TIMEOUT, .flags = 0x0, .termChar = 0x0 };

	Device_ReadResp* resp = device_read_1(&params, clnt);
	if (resp != NULL && resp->error == 0)
		return resp->data.data_len;
	else if (resp == NULL)
		return 0;
	else
		return -1;
}

int vxi11_docmd(unsigned long cmd) {
	if (clnt == NULL)
		return;

	Device_DocmdParms params = { .lid = link, .flags = 0x0, .io_timeout = VXI11_DEFAULT_TIMEOUT, .lock_timeout =
			VXI11_DEFAULT_TIMEOUT, .cmd = cmd, .network_order = 0, .datasize = 0 };

	params.data_in.data_in_len = 0;
	params.data_in.data_in_val = NULL;

	Device_DocmdResp* resp = device_docmd_1(&params, clnt);
	if (resp != NULL && resp->error == 0)
		return 1;
	else if (resp == NULL)
		return 0;
	else
		return -(resp->error);
}

int vxi11_trigger() {
	if (clnt == NULL)
		return;

	Device_GenericParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout =
			VXI11_DEFAULT_TIMEOUT };
	Device_Error* error = device_trigger_1(&params, clnt);

	if (error->error == 0)
		return 1;
	else
		return -1;
}

int vxi11_clear() {
	if (clnt == NULL)
		return;
	Device_GenericParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout =
			VXI11_DEFAULT_TIMEOUT };
	Device_Error* error = device_clear_1(&params, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_remote() {
	if (clnt == NULL)
		return;
	Device_GenericParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout =
			VXI11_DEFAULT_TIMEOUT };
	Device_Error* error = device_remote_1(&params, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_local() {
	if (clnt == NULL)
		return;
	Device_GenericParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT, .io_timeout =
			VXI11_DEFAULT_TIMEOUT };
	Device_Error* error = device_local_1(&params, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_lock() {
	if (clnt == NULL)
		return;
	Device_LockParms params = { .lid = link, .flags = 0x0, .lock_timeout = VXI11_DEFAULT_TIMEOUT };
	Device_Error* error = device_lock_1(&params, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_unlock() {
	if (clnt == NULL)
		return;
	Device_Error* error = device_unlock_1(&link, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_create_intr_chan() {
	if (clnt == NULL)
		return;
	Device_RemoteFunc remotefunc = { .hostAddr = 0x0, .hostPort = 0x0, .progNum = 0x0, .progVers = 0x0, .progFamily =
			DEVICE_TCP };
	Device_Error* error = create_intr_chan_1(&remotefunc, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_destroy_intr_chan() {
	if (clnt == NULL)
		return;
	Device_Error* error = destroy_intr_chan_1(NULL, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_abort() {
	if (clnt == NULL)
		return;
	Device_Error* error = device_abort_1(&link, clnt);
	if (error != NULL && error->error == 0)
		return 1;
	else if (error == NULL)
		return 0;
	else
		return -(error->error);
}

int vxi11_close() {
	Device_Error* error = destroy_link_1(&link, clnt);
	clnt_destroy(clnt);
	clnt = NULL;
	return 1;
}