[CCode (cprefix = "xmlrpc_", cheader_filename = "xmlrpc-c/base.h,xmlrpc-c/client.h")]
namespace XmlRpc {
	[Compact]
	[CCode (cname = "xmlrpc_client", free_function = "xmlrpc_client_destroy", cprefix = "xmlrpc_client_")]
	public class Client {
		public int version_major;
		public int version_minor;
		public int version_point;
		public static void init (int flags, string appname, string appversion);

		public static void create (XmlRpc.Env env, int flags, string appname, string appversion, XmlRpc.Value? parms, int nparms, out XmlRpc.Client cli);

		[CCode (instance_pos = 1.1)]
		public void call2 (XmlRpc.Env e, ServerInfo si, string method_name, XmlRpc.Value param, out XmlRpc.Value result);
		public static XmlRpc.Value call_server (XmlRpc.Env e, ServerInfo si, string method_name, string format, ...);
		public static XmlRpc.Value call_server_params (XmlRpc.Env e, ServerInfo si, string method_name, XmlRpc.Value values);
		//TODO: static void init2 ()
		//static XmlRpc.Value call (XmlRpc.Env env, string url, string method_name, string format, ...);
		public void setup_global_const (XmlRpc.Env e);
		public static void teardown_global_const ();
	}

	public enum Flags {
		NO_FLAGS = 0,
		SKIP_LIBWWW_INIT = 1
	}

	[Compact]
	[CCode (cname  = "xmlrpc_server_info", cprefix = "xmlrpc_server_info_")]
	public class ServerInfo {
		public ServerInfo (XmlRpc.Env env, string server_url);
		public ServerInfo copy (XmlRpc.Env e);
		public void free ();
		/* auth */
		[CCode (instance_pos = 1.1)]
		public void set_basic_auth (XmlRpc.Env e, string user, string pass);
		[CCode (instance_pos = 1.1)]
		public void set_user (XmlRpc.Env e, string user, string pass);
		[CCode (instance_pos = 1.1)]
		public void allow_auth_basic (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void disallow_auth_basic (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void allow_auth_digest (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void disallow_auth_digest (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void allow_auth_negotiate (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void disallow_auth_negotiate (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void allow_auth_ntlm (XmlRpc.Env e);
		[CCode (instance_pos = 1.1)]
		public void disallow_auth_ntlm (XmlRpc.Env e);
	}

	[Compact]
	[CCode (cprefix = "xmlrpc_value_", cname = "xmlrpc_value", ref_function = "xmlrpc_INCREF", ref_function_void = true, unref_function = "xmlrpc_DECREF", free_function = "")]
	public class Value {
		public XmlRpc.Type type ();
	}

	[CCode (cname = "xmlrpc_type", cprefix = "XMLRPC_TYPE_")]
	public enum Type {
		INT,
		BOOL,
		DOUBLE,
		DATETIME,
		STRING,
		BASE64,
		ARRAY,
		STRUCT,
		C_PTR,
		NIL,
		I8,
		DEAD
	}

	[CCode (cname  = "xmlrpc_env", cprefix = "xmlrpc_env_", free_function = "", destroy_function = "xmlrpc_env_clean")]
	public struct Env {
		public string fault_string;
		public int fault_code;
		public bool fault_occurred;

		public Env ();

		[CCode (cname = "xmlrpc_parse_response")]
		public XmlRpc.Value parse_response (string xmldata, int xmldata_len);

		/* create */
		public XmlRpc.Value struct_new ();
		public XmlRpc.Value array_new ();
		public XmlRpc.Value bool_new (bool v);
		[CCode (cname = "xmlrpc_string_new")]
		public XmlRpc.Value string_new (string str);
		[CCode (cname = "xmlrpc_int_new")]
		public XmlRpc.Value int_new (int num);
		[CCode (cname = "xmlrpc_double_new")]
		public XmlRpc.Value double_new (double v);

		/* read */
		[CCode (cname = "xmlrpc_read_bool")]
		public void read_bool (XmlRpc.Value v, out bool num);
		[CCode (cname = "xmlrpc_read_string")]
		public void read_string (XmlRpc.Value v, out unowned string str);
		[CCode (cname = "xmlrpc_read_int")]
		public void read_int (XmlRpc.Value v, out int num);
		[CCode (cname = "xmlrpc_read_double")]
		public void read_double (XmlRpc.Value v, out double num);

		/* struct */
		// TODO: move into StructValue
		[CCode (cname = "xmlrpc_struct_size")]
		public int struct_size (XmlRpc.Value stru);
		[CCode (cname = "xmlrpc_struct_has_key")]
		public bool struct_has_key (XmlRpc.Value stru, string key);
		[CCode (cname = "xmlrpc_struct_has_key_n")]
		public bool struct_has_key_n (XmlRpc.Value stru, string key, int key_len);
		[CCode (cname = "xmlrpc_struct_has_find_value")]
		public void struct_has_find_value (XmlRpc.Value stru, string key, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_has_find_value_v")]
		public void struct_has_find_value_v (XmlRpc.Value stru, string key, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_read_value")]
		public void struct_read_value (XmlRpc.Value stru, string key, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_read_value_v")]
		public void struct_read_value_v (XmlRpc.Value stru, XmlRpc.Value key, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_get_value")]
		public XmlRpc.Value struct_get_value (XmlRpc.Value stru, string key);
		[CCode (cname = "xmlrpc_struct_get_value_n")]
		public XmlRpc.Value struct_get_value_n (XmlRpc.Value stru, string key, int key_len);
		[CCode (cname = "xmlrpc_struct_set_value")]
		public void struct_set_value (XmlRpc.Value stru, string key, XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_set_value_n")]
		public void struct_set_value_n (XmlRpc.Value stru, string key, int key_len, XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_set_value_v")]
		public void struct_set_value_v (XmlRpc.Value stru, XmlRpc.Value keyval, XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_read_member")]
		public void struct_read_member (XmlRpc.Value stru, int idx, out XmlRpc.Value key, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_struct_get_key_and_value")]
		public void struct_get_key_and_value (XmlRpc.Value stru, int idx, out XmlRpc.Value key, out XmlRpc.Value v);
	}

	// experimental //
	[CCode (cname = "xmlrpc_value")]
	class Struct : Value {
		[CCode (cname = "xmlrpc_struct_new", instance_pos = 1.1)]
		public Struct  (XmlRpc.Env env);
		[CCode (cname = "xmlrpc_struct_size", instance_pos = 1.1)]
		public int size (XmlRpc.Env env);
		[CCode (cname = "xmlrpc_struct_set_value", instance_pos = 1.1)]
		public void set_value (XmlRpc.Env env, string key, XmlRpc.Value v);
	}

	[CCode (cname = "xmlrpc_value")]
	public class String : Value {
		[CCode (cname = "xmlrpc_string_new")]
		public String (string str);
		[CCode (cname = "xmlrpc_read_string", instance_pos = 1.1)]
		public void read (XmlRpc.Env env, out string value);
	}

	[CCode (cname = "xmlrpc_value")]
	public class Integer : Value {
		[CCode (cname = "xmlrpc_int_new")]
		public Integer (int num);
		[CCode (cname = "xmlrpc_read_int", instance_pos = 1.1)]
		public void read (XmlRpc.Env env, out int value);
	}

	[CCode (cname = "xmlrpc_value")]
	public class Array : Value {
		[CCode (cname = "xmlrpc_array_new", instance_pos = 1.1)]
		public Array (XmlRpc.Env env);
		[CCode (cname = "xmlrpc_array_size", instance_pos = 1.1)]
		public int size (XmlRpc.Env env);
		[CCode (cname = "xmlrpc_array_read_item", instance_pos = 1.1)]
		public void read_item (XmlRpc.Env env, int idx, out XmlRpc.Value v);
		[CCode (cname = "xmlrpc_array_append_item", instance_pos = 1.1)]
		public int append_item (XmlRpc.Env env, XmlRpc.Value b);
	}
}
