#ifndef CA_IF_H
#define CA_IF_H

/******************************************************************************
 * $HeadURL: https://svnpub.iter.org/codac/iter/codac/dev/units/m-log-lib/trunk/src/main/c++/include/tools/any-type.h $
 * $Id: any-type.h 50547 2014-10-09 12:09:51Z bauvirb $
 *
 * Project	: CODAC Core System
 *
 * Description	: Channel Access Interface
 *
 * Author        : Bertrand Bauvir
 *
 * Copyright (c) : 2010-2014 ITER Organization,
 *		  CS 90 046
 *		  13067 St. Paul-lez-Durance Cedex
 *		  France
 *
 * This file is part of ITER CODAC software.
 * For the terms and conditions of redistribution or use of this software
 * refer to the file ITER-LICENSE.TXT located in the top level directory
 * of the distribution package.
 ******************************************************************************/

/* Global header files */
#include <iostream>
#include <cadef.h> /* Channel Access API definition, etc. */
//#include <log.h> /* CCS logging library */

/* Local header files */

/* Constants */

#ifndef log_trace
#define log_trace(arg_msg...) {}
#endif

#ifndef log_error
#define log_error(arg_msg...){}
#endif

/* Type definition */

/* Global variables */

/* Public function declaration */

static inline bool CAInterface_Initialize(void) {
	bool status = false;
	ca_context_create (ca_disable_preemptive_callback); //Default
	//ca_context_create(ca_enable_preemptive_callback);
	status = true;

	return status;
};

static inline bool CAInterface_Finalize(void) {
	bool status = false;
	ca_context_destroy();
	status = true;

	return status;
};

static inline bool CAInterface_ConnectVariable(char* name, chid& id) {
	bool status = false;
	/* Connect to channels */
	if (ca_create_channel(name, NULL, NULL, 10, &id) != ECA_NORMAL) {
		return status;
	}

	/* Wait for connections */
	if (ca_pend_io(1) != ECA_NORMAL) {
		log_error("%s - ca_pend_io failed", __FUNCTION__);
		return status;
	}

	/* Verify channel */
	if (ca_state(id) != cs_conn) {
		//log_warning("Connection to channel '%s' has not been successful", name);
	} else {
		//log_info("Connection to channel '%s' has been successfully verified", name);
	}

	status = true;

	return status;
};

static inline bool CAInterface_ReadVariable(chid channel, chtype type,
		void* p_value) {
	bool status = false;
	if (ca_state(channel) != cs_conn) {
		//log_error("%s - Connection to channel has been lost");
		return status;
	}

	if (ca_get(type, channel, p_value) != ECA_NORMAL) {
		//log_error("%s - ca_get failed", __FUNCTION__);
		return status;
	}

	/* Flush the requests */
	if (ca_pend_io(1) != ECA_NORMAL) {
		//log_error("%s - ca_pend_io failed", __FUNCTION__);
		return status;
	}

	status = true;

	return status;
};

static inline bool CAInterface_WriteVariable(chid channel, chtype type,
		void* p_value) {
	bool status = false;

	if (ca_state(channel) != cs_conn) {
		//log_error("%s - Connection to channel has been lost", __FUNCTION__);
		return status;
	}

	if (ca_put(type, channel, p_value) != ECA_NORMAL) {
		//log_warning("%s - ca_put failed", __FUNCTION__);
	}

	/* Flush the requests */
	if (ca_pend_io(1) != ECA_NORMAL) {
		//log_error("%s - ca_pend_io failed", __FUNCTION__);
		return status;
	}

	status = true;

	return status;
};

typedef void (*pCallBack)(struct event_handler_args);

static inline bool CAInterface_SubscribeVariable(chid channel, chtype type,
		pCallBack cb_func, void* p_value) {
	bool status = false;
	if (ca_state(channel) != cs_conn) {
		//log_error("%s - Connection to channel has been lost", __FUNCTION__);
		return status;
	}

	if (ca_create_subscription(type, 0, channel, DBE_VALUE, cb_func, NULL, NULL)
			!= ECA_NORMAL) {
		//log_error("%s - ca_create_subscription failed", __FUNCTION__);
		return status;

	}
	/*
	 if(ca_pend_event(0.0) != ECA_NORMAL){
	 //log_error("%s - ca_pend_event failed", __FUNCTION__);
	 return status;
	 }
	 */
	status = true;

	return status;
};

#endif /* CA_IF_H */
