/* account_finder.c generated by valac 0.56.19, the Vala compiler
 * generated from account_finder.vala, do not modify */

#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <json-glib/json-glib.h>
#include <gobject/gvaluecollector.h>

#define DC_ACCOUNT_FINDER_RPC_BIN "deltachat-rpc-server"
#define DC_ACCOUNT_FINDER_RPC_BIN_FILE "deltachat-rpc-server"
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

typedef enum  {
	DC_RPC_SERVER_SOURCE_AUTO = 0,
	DC_RPC_SERVER_SOURCE_CUSTOM = 1
} DcRpcServerSource;

#define DC_TYPE_RPC_SERVER_SOURCE (dc_rpc_server_source_get_type ())

#define DC_TYPE_ACCOUNT_FINDER (dc_account_finder_get_type ())
#define DC_ACCOUNT_FINDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_ACCOUNT_FINDER, DcAccountFinder))
#define DC_ACCOUNT_FINDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_ACCOUNT_FINDER, DcAccountFinderClass))
#define DC_IS_ACCOUNT_FINDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_ACCOUNT_FINDER))
#define DC_IS_ACCOUNT_FINDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_ACCOUNT_FINDER))
#define DC_ACCOUNT_FINDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_ACCOUNT_FINDER, DcAccountFinderClass))

typedef struct _DcAccountFinder DcAccountFinder;
typedef struct _DcAccountFinderClass DcAccountFinderClass;
typedef struct _DcAccountFinderPrivate DcAccountFinderPrivate;
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

#define DC_TYPE_RPC_CLIENT (dc_rpc_client_get_type ())
#define DC_RPC_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DC_TYPE_RPC_CLIENT, DcRpcClient))
#define DC_RPC_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DC_TYPE_RPC_CLIENT, DcRpcClientClass))
#define DC_IS_RPC_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DC_TYPE_RPC_CLIENT))
#define DC_IS_RPC_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DC_TYPE_RPC_CLIENT))
#define DC_RPC_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DC_TYPE_RPC_CLIENT, DcRpcClientClass))

typedef struct _DcRpcClient DcRpcClient;
typedef struct _DcRpcClientClass DcRpcClientClass;
#define _json_object_unref0(var) ((var == NULL) ? NULL : (var = (json_object_unref (var), NULL)))
#define _json_array_unref0(var) ((var == NULL) ? NULL : (var = (json_array_unref (var), NULL)))
#define __vala_JsonNode_free0(var) ((var == NULL) ? NULL : (var = (_vala_JsonNode_free (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))
typedef struct _DcAccountFinderEnsureConfiguredData DcAccountFinderEnsureConfiguredData;
typedef struct _DcParamSpecAccountFinder DcParamSpecAccountFinder;

struct _DcAccountFinder {
	GTypeInstance parent_instance;
	volatile int ref_count;
	DcAccountFinderPrivate * priv;
};

struct _DcAccountFinderClass {
	GTypeClass parent_class;
	void (*finalize) (DcAccountFinder *self);
};

struct _DcAccountFinderEnsureConfiguredData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	DcRpcClient* rpc;
	gchar* preferred_addr;
	gchar* description;
	gchar* toast_msg;
	gint result;
	JsonNode* accounts_node;
	JsonNode* _tmp0_;
	JsonNode* _tmp1_;
	JsonArray* accounts;
	JsonNode* _tmp2_;
	JsonArray* _tmp3_;
	JsonArray* _tmp4_;
	gint first_id;
	gint preferred_id;
	gchar* want;
	gchar* _tmp5_;
	gchar* _tmp6_;
	gchar* _tmp7_;
	gchar* _tmp8_;
	guint i;
	gboolean _tmp9_;
	guint _tmp10_;
	JsonArray* _tmp11_;
	JsonObject* acct;
	JsonArray* _tmp12_;
	JsonObject* _tmp13_;
	JsonObject* _tmp14_;
	gint id;
	JsonObject* _tmp15_;
	gboolean _tmp16_;
	gboolean _tmp17_;
	const gchar* _tmp18_;
	gint _tmp19_;
	gint _tmp20_;
	gchar* addr;
	gchar* _tmp21_;
	gboolean _tmp22_;
	const gchar* _tmp23_;
	const gchar* _tmp24_;
	gchar* _tmp25_;
	gchar* _tmp26_;
	gchar* _tmp27_;
	gchar* _tmp28_;
	const gchar* _tmp29_;
	gint _tmp30_;
	gint chosen;
	gchar* _tmp31_;
	GError* e;
	GError* _tmp32_;
	const gchar* _tmp33_;
	gchar* _tmp34_;
	GError* _inner_error0_;
};

struct _DcParamSpecAccountFinder {
	GParamSpec parent_instance;
};

static gpointer dc_account_finder_parent_class = NULL;

VALA_EXTERN GType dc_rpc_server_source_get_type (void) G_GNUC_CONST ;
VALA_EXTERN gpointer dc_account_finder_ref (gpointer instance);
VALA_EXTERN void dc_account_finder_unref (gpointer instance);
VALA_EXTERN GParamSpec* dc_param_spec_account_finder (const gchar* name,
                                          const gchar* nick,
                                          const gchar* blurb,
                                          GType object_type,
                                          GParamFlags flags);
VALA_EXTERN void dc_value_set_account_finder (GValue* value,
                                  gpointer v_object);
VALA_EXTERN void dc_value_take_account_finder (GValue* value,
                                   gpointer v_object);
VALA_EXTERN gpointer dc_value_get_account_finder (const GValue* value);
VALA_EXTERN GType dc_account_finder_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcAccountFinder, dc_account_finder_unref)
VALA_EXTERN gchar* dc_account_finder_find_rpc_server (const gchar* custom_path,
                                          DcRpcServerSource source);
static gboolean dc_account_finder_is_executable (const gchar* path);
static gchar* dc_account_finder_find_standalone_rpc_server (void);
VALA_EXTERN gchar* dc_platform_get_executable_path (void);
VALA_EXTERN gchar* dc_account_finder_get_managed_rpc_path (void);
VALA_EXTERN gchar* dc_account_finder_get_parla_data_dir (void);
VALA_EXTERN gchar* dc_account_finder_get_data_dir (void);
static void dc_account_finder_ensure_configured_data_free (gpointer _data);
VALA_EXTERN GType dc_rpc_client_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (DcRpcClient, g_object_unref)
VALA_EXTERN void dc_account_finder_ensure_configured (DcRpcClient* rpc,
                                          const gchar* preferred_addr,
                                          GAsyncReadyCallback _callback_,
                                          gpointer _user_data_);
VALA_EXTERN gint dc_account_finder_ensure_configured_finish (GAsyncResult* _res_,
                                                 gchar** description,
                                                 gchar** toast_msg);
static gboolean dc_account_finder_ensure_configured_co (DcAccountFinderEnsureConfiguredData* _data_);
VALA_EXTERN void dc_rpc_client_get_all_accounts (DcRpcClient* self,
                                     GAsyncReadyCallback _callback_,
                                     gpointer _user_data_);
VALA_EXTERN JsonNode* dc_rpc_client_get_all_accounts_finish (DcRpcClient* self,
                                                 GAsyncResult* _res_,
                                                 GError** error);
static void dc_account_finder_ensure_configured_ready (GObject* source_object,
                                                GAsyncResult* _res_,
                                                gpointer _user_data_);
VALA_EXTERN void dc_rpc_client_is_configured (DcRpcClient* self,
                                  gint acct_id,
                                  GAsyncReadyCallback _callback_,
                                  gpointer _user_data_);
VALA_EXTERN gboolean dc_rpc_client_is_configured_finish (DcRpcClient* self,
                                             GAsyncResult* _res_,
                                             GError** error);
static void _vala_JsonNode_free (JsonNode* self);
VALA_EXTERN void dc_rpc_client_get_config (DcRpcClient* self,
                               const gchar* key,
                               gint acct_id,
                               GAsyncReadyCallback _callback_,
                               gpointer _user_data_);
VALA_EXTERN gchar* dc_rpc_client_get_config_finish (DcRpcClient* self,
                                        GAsyncResult* _res_,
                                        GError** error);
VALA_EXTERN void dc_rpc_client_set_account_id (DcRpcClient* self,
                                   gint value);
VALA_EXTERN void dc_rpc_client_select_account (DcRpcClient* self,
                                   gint acct_id,
                                   GAsyncReadyCallback _callback_,
                                   gpointer _user_data_);
VALA_EXTERN void dc_rpc_client_select_account_finish (DcRpcClient* self,
                                          GAsyncResult* _res_,
                                          GError** error);
VALA_EXTERN DcAccountFinder* dc_account_finder_new (void);
VALA_EXTERN DcAccountFinder* dc_account_finder_construct (GType object_type);
static void dc_account_finder_finalize (DcAccountFinder * obj);
static GType dc_account_finder_get_type_once (void);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

static GType
dc_rpc_server_source_get_type_once (void)
{
	static const GEnumValue values[] = {{DC_RPC_SERVER_SOURCE_AUTO, "DC_RPC_SERVER_SOURCE_AUTO", "auto"}, {DC_RPC_SERVER_SOURCE_CUSTOM, "DC_RPC_SERVER_SOURCE_CUSTOM", "custom"}, {0, NULL, NULL}};
	GType dc_rpc_server_source_type_id;
	dc_rpc_server_source_type_id = g_enum_register_static ("DcRpcServerSource", values);
	return dc_rpc_server_source_type_id;
}

GType
dc_rpc_server_source_get_type (void)
{
	static volatile gsize dc_rpc_server_source_type_id__once = 0;
	if (g_once_init_enter (&dc_rpc_server_source_type_id__once)) {
		GType dc_rpc_server_source_type_id;
		dc_rpc_server_source_type_id = dc_rpc_server_source_get_type_once ();
		g_once_init_leave (&dc_rpc_server_source_type_id__once, dc_rpc_server_source_type_id);
	}
	return dc_rpc_server_source_type_id__once;
}

/**
         * Return an absolute path to deltachat-rpc-server, or null if none found.
         *
         * Custom mode is exclusive so broken explicit choices can be surfaced
         * instead of silently falling back.
         */
gchar*
dc_account_finder_find_rpc_server (const gchar* custom_path,
                                   DcRpcServerSource source)
{
	gchar* result;
	switch (source) {
		case DC_RPC_SERVER_SOURCE_CUSTOM:
		{
			const gchar* _tmp0_ = NULL;
			gchar* _tmp1_;
			if (dc_account_finder_is_executable (custom_path)) {
				_tmp0_ = custom_path;
			} else {
				_tmp0_ = NULL;
			}
			_tmp1_ = g_strdup (_tmp0_);
			result = _tmp1_;
			return result;
		}
		default:
		case DC_RPC_SERVER_SOURCE_AUTO:
		{
			gchar* _tmp2_;
			_tmp2_ = dc_account_finder_find_standalone_rpc_server ();
			result = _tmp2_;
			return result;
		}
	}
}

static gchar*
dc_account_finder_find_standalone_rpc_server (void)
{
	gchar* env_path = NULL;
	const gchar* _tmp0_;
	gchar* _tmp1_;
	gboolean _tmp2_ = FALSE;
	const gchar* _tmp3_;
	gchar* exe_path = NULL;
	gchar* _tmp11_;
	const gchar* _tmp12_;
	gchar* in_path = NULL;
	gchar* _tmp29_;
	const gchar* _tmp30_;
	gchar* home = NULL;
	const gchar* _tmp31_;
	gchar* _tmp32_;
	gchar** user_bins = NULL;
	const gchar* _tmp33_;
	gchar* _tmp34_;
	const gchar* _tmp35_;
	gchar* _tmp36_;
	gchar** _tmp37_;
	gint user_bins_length1;
	gint _user_bins_size_;
	gchar** _tmp38_;
	gint _tmp38__length1;
	gchar* managed = NULL;
	gchar* _tmp41_;
	gboolean _tmp42_ = FALSE;
	const gchar* _tmp43_;
	const gchar* _tmp46_;
	gchar* result;
	_tmp0_ = g_getenv ("PARLA_RPC_SERVER");
	_tmp1_ = g_strdup (_tmp0_);
	env_path = _tmp1_;
	_tmp3_ = env_path;
	if (_tmp3_ != NULL) {
		const gchar* _tmp4_;
		gint _tmp5_;
		gint _tmp6_;
		_tmp4_ = env_path;
		_tmp5_ = strlen (_tmp4_);
		_tmp6_ = _tmp5_;
		_tmp2_ = _tmp6_ > 0;
	} else {
		_tmp2_ = FALSE;
	}
	if (_tmp2_) {
		const gchar* _tmp7_ = NULL;
		const gchar* _tmp8_;
		gchar* _tmp10_;
		_tmp8_ = env_path;
		if (dc_account_finder_is_executable (_tmp8_)) {
			const gchar* _tmp9_;
			_tmp9_ = env_path;
			_tmp7_ = _tmp9_;
		} else {
			_tmp7_ = NULL;
		}
		_tmp10_ = g_strdup (_tmp7_);
		result = _tmp10_;
		_g_free0 (env_path);
		return result;
	}
	_tmp11_ = dc_platform_get_executable_path ();
	exe_path = _tmp11_;
	_tmp12_ = exe_path;
	if (_tmp12_ != NULL) {
		gchar* exe_dir = NULL;
		const gchar* _tmp13_;
		gchar* _tmp14_;
		gchar* prefix = NULL;
		const gchar* _tmp15_;
		gchar* _tmp16_;
		gchar** packaged = NULL;
		const gchar* _tmp17_;
		gchar* _tmp18_;
		const gchar* _tmp19_;
		gchar* _tmp20_;
		const gchar* _tmp21_;
		gchar* _tmp22_;
		gchar* _tmp23_;
		gchar* _tmp24_;
		gchar** _tmp25_;
		gint packaged_length1;
		gint _packaged_size_;
		gchar** _tmp26_;
		gint _tmp26__length1;
		_tmp13_ = exe_path;
		_tmp14_ = g_path_get_dirname (_tmp13_);
		exe_dir = _tmp14_;
		_tmp15_ = exe_dir;
		_tmp16_ = g_path_get_dirname (_tmp15_);
		prefix = _tmp16_;
		_tmp17_ = exe_dir;
		_tmp18_ = g_build_filename (_tmp17_, DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
		_tmp19_ = prefix;
		_tmp20_ = g_build_filename (_tmp19_, "libexec", "parla", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
		_tmp21_ = prefix;
		_tmp22_ = g_build_filename (_tmp21_, "lib", "parla", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
		_tmp23_ = g_build_filename ("/app", "bin", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
		_tmp24_ = g_build_filename ("/app", "libexec", "parla", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
		_tmp25_ = g_new0 (gchar*, 5 + 1);
		_tmp25_[0] = _tmp18_;
		_tmp25_[1] = _tmp20_;
		_tmp25_[2] = _tmp22_;
		_tmp25_[3] = _tmp23_;
		_tmp25_[4] = _tmp24_;
		packaged = _tmp25_;
		packaged_length1 = 5;
		_packaged_size_ = packaged_length1;
		_tmp26_ = packaged;
		_tmp26__length1 = packaged_length1;
		{
			gchar** candidate_collection = NULL;
			gint candidate_collection_length1 = 0;
			gint _candidate_collection_size_ = 0;
			gint candidate_it = 0;
			candidate_collection = _tmp26_;
			candidate_collection_length1 = _tmp26__length1;
			for (candidate_it = 0; candidate_it < candidate_collection_length1; candidate_it = candidate_it + 1) {
				gchar* _tmp27_;
				gchar* candidate = NULL;
				_tmp27_ = g_strdup (candidate_collection[candidate_it]);
				candidate = _tmp27_;
				{
					const gchar* _tmp28_;
					_tmp28_ = candidate;
					if (dc_account_finder_is_executable (_tmp28_)) {
						result = candidate;
						packaged = (_vala_array_free (packaged, packaged_length1, (GDestroyNotify) g_free), NULL);
						_g_free0 (prefix);
						_g_free0 (exe_dir);
						_g_free0 (exe_path);
						_g_free0 (env_path);
						return result;
					}
					_g_free0 (candidate);
				}
			}
		}
		packaged = (_vala_array_free (packaged, packaged_length1, (GDestroyNotify) g_free), NULL);
		_g_free0 (prefix);
		_g_free0 (exe_dir);
	}
	_tmp29_ = g_find_program_in_path (DC_ACCOUNT_FINDER_RPC_BIN);
	in_path = _tmp29_;
	_tmp30_ = in_path;
	if (_tmp30_ != NULL) {
		result = in_path;
		_g_free0 (exe_path);
		_g_free0 (env_path);
		return result;
	}
	_tmp31_ = g_get_home_dir ();
	_tmp32_ = g_strdup (_tmp31_);
	home = _tmp32_;
	_tmp33_ = home;
	_tmp34_ = g_build_filename (_tmp33_, ".local", "bin", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
	_tmp35_ = home;
	_tmp36_ = g_build_filename (_tmp35_, ".cargo", "bin", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
	_tmp37_ = g_new0 (gchar*, 2 + 1);
	_tmp37_[0] = _tmp34_;
	_tmp37_[1] = _tmp36_;
	user_bins = _tmp37_;
	user_bins_length1 = 2;
	_user_bins_size_ = user_bins_length1;
	_tmp38_ = user_bins;
	_tmp38__length1 = user_bins_length1;
	{
		gchar** candidate_collection = NULL;
		gint candidate_collection_length1 = 0;
		gint _candidate_collection_size_ = 0;
		gint candidate_it = 0;
		candidate_collection = _tmp38_;
		candidate_collection_length1 = _tmp38__length1;
		for (candidate_it = 0; candidate_it < candidate_collection_length1; candidate_it = candidate_it + 1) {
			gchar* _tmp39_;
			gchar* candidate = NULL;
			_tmp39_ = g_strdup (candidate_collection[candidate_it]);
			candidate = _tmp39_;
			{
				const gchar* _tmp40_;
				_tmp40_ = candidate;
				if (dc_account_finder_is_executable (_tmp40_)) {
					result = candidate;
					user_bins = (_vala_array_free (user_bins, user_bins_length1, (GDestroyNotify) g_free), NULL);
					_g_free0 (home);
					_g_free0 (in_path);
					_g_free0 (exe_path);
					_g_free0 (env_path);
					return result;
				}
				_g_free0 (candidate);
			}
		}
	}
	_tmp41_ = dc_account_finder_get_managed_rpc_path ();
	managed = _tmp41_;
	_tmp43_ = managed;
	if (g_file_test (_tmp43_, G_FILE_TEST_EXISTS)) {
		const gchar* _tmp44_;
		_tmp44_ = managed;
		_tmp42_ = !g_file_test (_tmp44_, G_FILE_TEST_IS_EXECUTABLE);
	} else {
		_tmp42_ = FALSE;
	}
	if (_tmp42_) {
		const gchar* _tmp45_;
		_tmp45_ = managed;
		g_chmod (_tmp45_, 0755);
	}
	_tmp46_ = managed;
	if (dc_account_finder_is_executable (_tmp46_)) {
		result = managed;
		user_bins = (_vala_array_free (user_bins, user_bins_length1, (GDestroyNotify) g_free), NULL);
		_g_free0 (home);
		_g_free0 (in_path);
		_g_free0 (exe_path);
		_g_free0 (env_path);
		return result;
	}
	result = NULL;
	_g_free0 (managed);
	user_bins = (_vala_array_free (user_bins, user_bins_length1, (GDestroyNotify) g_free), NULL);
	_g_free0 (home);
	_g_free0 (in_path);
	_g_free0 (exe_path);
	_g_free0 (env_path);
	return result;
}

/**
         * Path to the Parla-managed (self-downloaded) server binary. Kept here
         * so discovery and RpcInstaller agree on a single location.
         */
gchar*
dc_account_finder_get_managed_rpc_path (void)
{
	gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* result;
	_tmp0_ = dc_account_finder_get_parla_data_dir ();
	_tmp1_ = _tmp0_;
	_tmp2_ = g_build_filename (_tmp1_, "bin", DC_ACCOUNT_FINDER_RPC_BIN_FILE, NULL);
	_tmp3_ = _tmp2_;
	_g_free0 (_tmp1_);
	result = _tmp3_;
	return result;
}

static gboolean
dc_account_finder_is_executable (const gchar* path)
{
	gboolean _tmp0_ = FALSE;
	gboolean _tmp1_ = FALSE;
	gboolean result;
	if (path != NULL) {
		gint _tmp2_;
		gint _tmp3_;
		_tmp2_ = strlen (path);
		_tmp3_ = _tmp2_;
		_tmp1_ = _tmp3_ > 0;
	} else {
		_tmp1_ = FALSE;
	}
	if (_tmp1_) {
		_tmp0_ = g_file_test (path, G_FILE_TEST_IS_EXECUTABLE);
	} else {
		_tmp0_ = FALSE;
	}
	result = _tmp0_;
	return result;
}

/**
         * Return Parla's private Delta Chat data directory. Existing early
         * Parla accounts under ~/.config/parla are kept in place.
         */
gchar*
dc_account_finder_get_parla_data_dir (void)
{
	gchar* data_dir = NULL;
	const gchar* _tmp0_;
	gchar* _tmp1_;
	gchar* old_config_dir = NULL;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gchar* data_accounts = NULL;
	const gchar* _tmp4_;
	gchar* _tmp5_;
	gchar* old_accounts = NULL;
	const gchar* _tmp6_;
	gchar* _tmp7_;
	gboolean _tmp8_ = FALSE;
	const gchar* _tmp9_;
	const gchar* _tmp11_;
	gchar* result;
	_tmp0_ = g_get_user_data_dir ();
	_tmp1_ = g_build_filename (_tmp0_, "parla", NULL);
	data_dir = _tmp1_;
	_tmp2_ = g_get_user_config_dir ();
	_tmp3_ = g_build_filename (_tmp2_, "parla", NULL);
	old_config_dir = _tmp3_;
	_tmp4_ = data_dir;
	_tmp5_ = g_build_filename (_tmp4_, "accounts", NULL);
	data_accounts = _tmp5_;
	_tmp6_ = old_config_dir;
	_tmp7_ = g_build_filename (_tmp6_, "accounts", NULL);
	old_accounts = _tmp7_;
	_tmp9_ = data_accounts;
	if (!g_file_test (_tmp9_, G_FILE_TEST_IS_DIR)) {
		const gchar* _tmp10_;
		_tmp10_ = old_accounts;
		_tmp8_ = g_file_test (_tmp10_, G_FILE_TEST_IS_DIR);
	} else {
		_tmp8_ = FALSE;
	}
	if (_tmp8_) {
		result = old_config_dir;
		_g_free0 (old_accounts);
		_g_free0 (data_accounts);
		_g_free0 (data_dir);
		return result;
	}
	_tmp11_ = data_dir;
	g_mkdir_with_parents (_tmp11_, 0700);
	result = data_dir;
	_g_free0 (old_accounts);
	_g_free0 (data_accounts);
	_g_free0 (old_config_dir);
	return result;
}

gchar*
dc_account_finder_get_data_dir (void)
{
	gchar* _tmp0_;
	gchar* result;
	_tmp0_ = dc_account_finder_get_parla_data_dir ();
	result = _tmp0_;
	return result;
}

static void
dc_account_finder_ensure_configured_data_free (gpointer _data)
{
	DcAccountFinderEnsureConfiguredData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->rpc);
	_g_free0 (_data_->preferred_addr);
	g_slice_free (DcAccountFinderEnsureConfiguredData, _data_);
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

void
dc_account_finder_ensure_configured (DcRpcClient* rpc,
                                     const gchar* preferred_addr,
                                     GAsyncReadyCallback _callback_,
                                     gpointer _user_data_)
{
	DcAccountFinderEnsureConfiguredData* _data_;
	DcRpcClient* _tmp0_;
	gchar* _tmp1_;
	g_return_if_fail (rpc != NULL);
	g_return_if_fail (preferred_addr != NULL);
	_data_ = g_slice_new0 (DcAccountFinderEnsureConfiguredData);
	_data_->_async_result = g_task_new (NULL, NULL, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, dc_account_finder_ensure_configured_data_free);
	_tmp0_ = _g_object_ref0 (rpc);
	_g_object_unref0 (_data_->rpc);
	_data_->rpc = _tmp0_;
	_tmp1_ = g_strdup (preferred_addr);
	_g_free0 (_data_->preferred_addr);
	_data_->preferred_addr = _tmp1_;
	dc_account_finder_ensure_configured_co (_data_);
}

gint
dc_account_finder_ensure_configured_finish (GAsyncResult* _res_,
                                            gchar** description,
                                            gchar** toast_msg)
{
	gint result;
	DcAccountFinderEnsureConfiguredData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
	if (description) {
		*description = _data_->description;
	} else {
		_g_free0 (_data_->description);
	}
	_data_->description = NULL;
	if (toast_msg) {
		*toast_msg = _data_->toast_msg;
	} else {
		_g_free0 (_data_->toast_msg);
	}
	_data_->toast_msg = NULL;
	result = _data_->result;
	return result;
}

/**
         * Activate a configured account on startup. If `preferred_addr` is
         * non-empty and matches a configured account, that one is chosen;
         * otherwise the first configured account is used. Returns its id
         * (>0) on success, or 0 with a human-readable status in
         * `description`.
         */
static void
dc_account_finder_ensure_configured_ready (GObject* source_object,
                                           GAsyncResult* _res_,
                                           gpointer _user_data_)
{
	DcAccountFinderEnsureConfiguredData* _data_;
	_data_ = _user_data_;
	_data_->_source_object_ = source_object;
	_data_->_res_ = _res_;
	dc_account_finder_ensure_configured_co (_data_);
}

static gpointer
_json_array_ref0 (gpointer self)
{
	return self ? json_array_ref (self) : NULL;
}

static gchar*
string_strip (const gchar* self)
{
	gchar* _result_ = NULL;
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_strdup (self);
	_result_ = _tmp0_;
	g_strstrip (_result_);
	result = _result_;
	return result;
}

static gpointer
_json_object_ref0 (gpointer self)
{
	return self ? json_object_ref (self) : NULL;
}

static void
_vala_JsonNode_free (JsonNode* self)
{
	g_boxed_free (json_node_get_type (), self);
}

static gboolean
dc_account_finder_ensure_configured_co (DcAccountFinderEnsureConfiguredData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		case 2:
		goto _state_2;
		case 3:
		goto _state_3;
		case 4:
		goto _state_4;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_g_free0 (_data_->description);
	_data_->description = NULL;
	_g_free0 (_data_->toast_msg);
	_data_->toast_msg = NULL;
	{
		_data_->_state_ = 1;
		dc_rpc_client_get_all_accounts (_data_->rpc, dc_account_finder_ensure_configured_ready, _data_);
		return FALSE;
		_state_1:
		_data_->_tmp0_ = dc_rpc_client_get_all_accounts_finish (_data_->rpc, _data_->_res_, &_data_->_inner_error0_);
		_data_->accounts_node = _data_->_tmp0_;
		if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
			goto __catch0_g_error;
		}
		_data_->_tmp1_ = _data_->accounts_node;
		if (_data_->_tmp1_ != NULL) {
			_data_->_tmp2_ = _data_->accounts_node;
			_data_->_tmp3_ = json_node_get_array (_data_->_tmp2_);
			_data_->_tmp4_ = _json_array_ref0 (_data_->_tmp3_);
			_data_->accounts = _data_->_tmp4_;
			_data_->first_id = 0;
			_data_->preferred_id = 0;
			_data_->_tmp5_ = g_utf8_strdown (_data_->preferred_addr, (gssize) -1);
			_data_->_tmp6_ = _data_->_tmp5_;
			_data_->_tmp7_ = string_strip (_data_->_tmp6_);
			_data_->_tmp8_ = _data_->_tmp7_;
			_g_free0 (_data_->_tmp6_);
			_data_->want = _data_->_tmp8_;
			{
				_data_->i = (guint) 0;
				{
					_data_->_tmp9_ = TRUE;
					while (TRUE) {
						if (!_data_->_tmp9_) {
							_data_->_tmp10_ = _data_->i;
							_data_->i = _data_->_tmp10_ + 1;
						}
						_data_->_tmp9_ = FALSE;
						_data_->_tmp11_ = _data_->accounts;
						if (!(_data_->i < json_array_get_length (_data_->_tmp11_))) {
							break;
						}
						_data_->_tmp12_ = _data_->accounts;
						_data_->_tmp13_ = json_array_get_object_element (_data_->_tmp12_, _data_->i);
						_data_->_tmp14_ = _json_object_ref0 (_data_->_tmp13_);
						_data_->acct = _data_->_tmp14_;
						_data_->_tmp15_ = _data_->acct;
						_data_->id = (gint) json_object_get_int_member (_data_->_tmp15_, "id");
						_data_->_state_ = 2;
						dc_rpc_client_is_configured (_data_->rpc, _data_->id, dc_account_finder_ensure_configured_ready, _data_);
						return FALSE;
						_state_2:
						_data_->_tmp16_ = dc_rpc_client_is_configured_finish (_data_->rpc, _data_->_res_, &_data_->_inner_error0_);
						if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
							_json_object_unref0 (_data_->acct);
							_g_free0 (_data_->want);
							_json_array_unref0 (_data_->accounts);
							__vala_JsonNode_free0 (_data_->accounts_node);
							goto __catch0_g_error;
						}
						if (!_data_->_tmp16_) {
							_json_object_unref0 (_data_->acct);
							continue;
						}
						if (_data_->first_id == 0) {
							_data_->first_id = _data_->id;
						}
						_data_->_tmp18_ = _data_->want;
						_data_->_tmp19_ = strlen (_data_->_tmp18_);
						_data_->_tmp20_ = _data_->_tmp19_;
						if (_data_->_tmp20_ > 0) {
							_data_->_tmp17_ = _data_->preferred_id == 0;
						} else {
							_data_->_tmp17_ = FALSE;
						}
						if (_data_->_tmp17_) {
							_data_->_state_ = 3;
							dc_rpc_client_get_config (_data_->rpc, "addr", _data_->id, dc_account_finder_ensure_configured_ready, _data_);
							return FALSE;
							_state_3:
							_data_->_tmp21_ = dc_rpc_client_get_config_finish (_data_->rpc, _data_->_res_, &_data_->_inner_error0_);
							_data_->addr = _data_->_tmp21_;
							if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
								_json_object_unref0 (_data_->acct);
								_g_free0 (_data_->want);
								_json_array_unref0 (_data_->accounts);
								__vala_JsonNode_free0 (_data_->accounts_node);
								goto __catch0_g_error;
							}
							_data_->_tmp23_ = _data_->addr;
							if (_data_->_tmp23_ != NULL) {
								_data_->_tmp24_ = _data_->addr;
								_data_->_tmp25_ = g_utf8_strdown (_data_->_tmp24_, (gssize) -1);
								_data_->_tmp26_ = _data_->_tmp25_;
								_data_->_tmp27_ = string_strip (_data_->_tmp26_);
								_data_->_tmp28_ = _data_->_tmp27_;
								_data_->_tmp29_ = _data_->want;
								_data_->_tmp22_ = g_strcmp0 (_data_->_tmp28_, _data_->_tmp29_) == 0;
								_g_free0 (_data_->_tmp28_);
								_g_free0 (_data_->_tmp26_);
							} else {
								_data_->_tmp22_ = FALSE;
							}
							if (_data_->_tmp22_) {
								_data_->preferred_id = _data_->id;
							}
							_g_free0 (_data_->addr);
						}
						_json_object_unref0 (_data_->acct);
					}
				}
			}
			if (_data_->preferred_id > 0) {
				_data_->_tmp30_ = _data_->preferred_id;
			} else {
				_data_->_tmp30_ = _data_->first_id;
			}
			_data_->chosen = _data_->_tmp30_;
			if (_data_->chosen > 0) {
				dc_rpc_client_set_account_id (_data_->rpc, _data_->chosen);
				_data_->_state_ = 4;
				dc_rpc_client_select_account (_data_->rpc, _data_->chosen, dc_account_finder_ensure_configured_ready, _data_);
				return FALSE;
				_state_4:
				dc_rpc_client_select_account_finish (_data_->rpc, _data_->_res_, &_data_->_inner_error0_);
				if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
					_g_free0 (_data_->want);
					_json_array_unref0 (_data_->accounts);
					__vala_JsonNode_free0 (_data_->accounts_node);
					goto __catch0_g_error;
				}
				_data_->result = _data_->chosen;
				_g_free0 (_data_->want);
				_json_array_unref0 (_data_->accounts);
				__vala_JsonNode_free0 (_data_->accounts_node);
				g_task_return_pointer (_data_->_async_result, _data_, NULL);
				if (_data_->_state_ != 0) {
					while (!g_task_get_completed (_data_->_async_result)) {
						g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
					}
				}
				g_object_unref (_data_->_async_result);
				return FALSE;
			}
			_g_free0 (_data_->want);
			_json_array_unref0 (_data_->accounts);
		}
		_data_->_tmp31_ = g_strdup ("No Delta Chat accounts configured.\n" "Add an account from the top left empty avatar icon to connect.");
		_g_free0 (_data_->description);
		_data_->description = _data_->_tmp31_;
		__vala_JsonNode_free0 (_data_->accounts_node);
	}
	goto __finally0;
	__catch0_g_error:
	{
		_data_->e = _data_->_inner_error0_;
		_data_->_inner_error0_ = NULL;
		_data_->_tmp32_ = _data_->e;
		_data_->_tmp33_ = _data_->_tmp32_->message;
		_data_->_tmp34_ = g_strconcat ("Account setup error: ", _data_->_tmp33_, NULL);
		_g_free0 (_data_->toast_msg);
		_data_->toast_msg = _data_->_tmp34_;
		_g_error_free0 (_data_->e);
	}
	__finally0:
	if (G_UNLIKELY (_data_->_inner_error0_ != NULL)) {
		_g_free0 (_data_->description);
		_g_free0 (_data_->toast_msg);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _data_->_inner_error0_->message, g_quark_to_string (_data_->_inner_error0_->domain), _data_->_inner_error0_->code);
		g_clear_error (&_data_->_inner_error0_);
		g_object_unref (_data_->_async_result);
		return FALSE;
	}
	_data_->result = 0;
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

DcAccountFinder*
dc_account_finder_construct (GType object_type)
{
	DcAccountFinder* self = NULL;
	self = (DcAccountFinder*) g_type_create_instance (object_type);
	return self;
}

DcAccountFinder*
dc_account_finder_new (void)
{
	return dc_account_finder_construct (DC_TYPE_ACCOUNT_FINDER);
}

static void
dc_value_account_finder_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
dc_value_account_finder_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		dc_account_finder_unref (value->data[0].v_pointer);
	}
}

static void
dc_value_account_finder_copy_value (const GValue* src_value,
                                    GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = dc_account_finder_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
dc_value_account_finder_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
dc_value_account_finder_collect_value (GValue* value,
                                       guint n_collect_values,
                                       GTypeCValue* collect_values,
                                       guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		DcAccountFinder * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = dc_account_finder_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
dc_value_account_finder_lcopy_value (const GValue* value,
                                     guint n_collect_values,
                                     GTypeCValue* collect_values,
                                     guint collect_flags)
{
	DcAccountFinder ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = dc_account_finder_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
dc_param_spec_account_finder (const gchar* name,
                              const gchar* nick,
                              const gchar* blurb,
                              GType object_type,
                              GParamFlags flags)
{
	DcParamSpecAccountFinder* spec;
	g_return_val_if_fail (g_type_is_a (object_type, DC_TYPE_ACCOUNT_FINDER), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
dc_value_get_account_finder (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_ACCOUNT_FINDER), NULL);
	return value->data[0].v_pointer;
}

void
dc_value_set_account_finder (GValue* value,
                             gpointer v_object)
{
	DcAccountFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_ACCOUNT_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DC_TYPE_ACCOUNT_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		dc_account_finder_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		dc_account_finder_unref (old);
	}
}

void
dc_value_take_account_finder (GValue* value,
                              gpointer v_object)
{
	DcAccountFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, DC_TYPE_ACCOUNT_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, DC_TYPE_ACCOUNT_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		dc_account_finder_unref (old);
	}
}

static void
dc_account_finder_class_init (DcAccountFinderClass * klass,
                              gpointer klass_data)
{
	dc_account_finder_parent_class = g_type_class_peek_parent (klass);
	((DcAccountFinderClass *) klass)->finalize = dc_account_finder_finalize;
}

static void
dc_account_finder_instance_init (DcAccountFinder * self,
                                 gpointer klass)
{
	self->ref_count = 1;
}

static void
dc_account_finder_finalize (DcAccountFinder * obj)
{
	DcAccountFinder * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, DC_TYPE_ACCOUNT_FINDER, DcAccountFinder);
	g_signal_handlers_destroy (self);
}

/**
     * Locates standalone, Parla-owned or distro-provided
     * deltachat-rpc-server binaries.
     */
static GType
dc_account_finder_get_type_once (void)
{
	static const GTypeValueTable g_define_type_value_table = { dc_value_account_finder_init, dc_value_account_finder_free_value, dc_value_account_finder_copy_value, dc_value_account_finder_peek_pointer, "p", dc_value_account_finder_collect_value, "p", dc_value_account_finder_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (DcAccountFinderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) dc_account_finder_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (DcAccountFinder), 0, (GInstanceInitFunc) dc_account_finder_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	GType dc_account_finder_type_id;
	dc_account_finder_type_id = g_type_register_fundamental (g_type_fundamental_next (), "DcAccountFinder", &g_define_type_info, &g_define_type_fundamental_info, 0);
	return dc_account_finder_type_id;
}

GType
dc_account_finder_get_type (void)
{
	static volatile gsize dc_account_finder_type_id__once = 0;
	if (g_once_init_enter (&dc_account_finder_type_id__once)) {
		GType dc_account_finder_type_id;
		dc_account_finder_type_id = dc_account_finder_get_type_once ();
		g_once_init_leave (&dc_account_finder_type_id__once, dc_account_finder_type_id);
	}
	return dc_account_finder_type_id__once;
}

gpointer
dc_account_finder_ref (gpointer instance)
{
	DcAccountFinder * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
dc_account_finder_unref (gpointer instance)
{
	DcAccountFinder * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		DC_ACCOUNT_FINDER_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

