/**	\author    coidgen 0.7.4
	\version    (0.0 build 1)
	\date      
	\brief     
*/

#ifndef __COID_CLIENT__example_h
#define __COID_CLIENT__example_h


#define CLIENT__example_h



#include "coid/coidclient/coidclient.h"
#include "coid/comm/sync/mutex_reg.h"


extern const version COID_version_example_0_0;


///Example struct used for argument in methods
struct FOO_STRUCT
{
    charstr message;
    int * array;
    int size;

    FOO_STRUCT() : array(NULL), size(0) {}

    FOO_STRUCT & operator = ( const FOO_STRUCT & x ) {
        message = x.message; size = x.size;
        if( array ) {delete array; array = NULL;}
        if( size ) {
            array = new int[size];
            memcpy( array, x.array, size * sizeof(int *) );
        }
        return *this;
    }
    
    ///write object to stream
    friend binstream & operator << ( binstream & b, const FOO_STRUCT & x ) {
        b << x.message << x.size;
        if( x.size ) b.write_raw( x.array, x.size * sizeof(int *) );
        return b;
    }
    
    ///read object from stream
    friend binstream & operator >> ( binstream & b, FOO_STRUCT & x ) {
        b >> x.message >> x.size;
        if( x.array ) {delete x.array; x.array = NULL;}
        if( x.size ) {
            x.array = new int[x.size];
            b.read_raw( x.array, x.size * sizeof(int *) );
        }
        return b;
    }
};

///Structure for remapping example, client side
struct REMAP_EXAMPLE_clientside
{
    charstr err_text;
    friend binstream & operator >> ( binstream & b, REMAP_EXAMPLE_clientside & x ) {
        x.err_text.reset();
        int tmp;
        b >> tmp;
        if( tmp ) {
            char * str = x.err_text.get_append_buf( tmp+1 );
            b.read_raw( str, tmp );
            str[tmp] = 0;
        }
        return b;
    }
};




namespace coid {


struct COID_TABLE_example_0_0;


///Example decorated class
class example_client
{
private:
	COID_TABLE_example_0_0 * _me;
	COID_TABLE_example_0_0 * _vtbl;
	mutable comm_mutex_custom_reg<netstream, void*> _mx_reg;
	mutable mexestream _mexestream;
	uint _conn_data;
	charstr _addr;

	void set_connection_type( uint ct ) {_conn_data = ct;}
	void destroy_me();

public:
	example_client();
	~example_client();
	example_client( const example_client & c );
	example_client & operator = ( const example_client & c );

	bool is_connected() const {return _me != NULL;}
	opcd disconnect();
	const char * get_addr() const {return _addr;}
	comm_mutex_reg * get_mx() {return &_mx_reg;}
	opcd get_last_error() const;
	void set_last_error( opcd e );
	uint get_connection_type() const {return _conn_data;}
	void setup_stream( binstream & b, uint coid_flags, uint coid_obj_id );
	bool setup_members( uint coid_stream_flags, netstream * bstream, binstream * bstream2=NULL, comm_mutex_reg * mx_reg=NULL );

	static const version & get_version() { return COID_version_example_0_0; }


public:
	opcd connect(  const charstr & name, const password & pwd, const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE );
	opcd connect_within(  comm_mutex_reg & coid_channel, const charstr & name, const password & pwd );
	opcd connect_shared( uint coid_obj_id,  const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE  );

	//user functions
	opcd read1( FOO_STRUCT & list );
	opcd read2( FOO_STRUCT & list );
	opcd send( int & ref, const charstr & command, binstreambuf & reply ) const;
	opcd remap_fnc( REMAP_EXAMPLE_clientside & remapped_arg );
	//method available only in direct (client&server in the same process) mode
	opcd get_ptr( FOO_STRUCT ** f );
};

} // namespace coid


#endif	// ! __COID_CLIENT__example_h