/* Here we actually tell opensync which sinks are available. */
static osync_bool discover(void *userdata, OSyncPluginInfo *info, OSyncError **error)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, userdata, info, error);

//	plugin_environment *env = (plugin_environment *)userdata;

	// Report avaliable sinks...
	OSyncObjTypeSink *sink = osync_plugin_info_find_objtype(info, "<objtype e.g. note>");
	if (!sink) {
		return FALSE;
	}
	osync_objtype_sink_set_available(sink, TRUE);
	
	OSyncVersion *version = osync_version_new(error);
	osync_version_set_plugin(version, "<your plugin-name>");
	//osync_version_set_version(version, "version");
	//osync_version_set_modelversion(version, "version");
	//osync_version_set_firmwareversion(version, "firmwareversion");
	//osync_version_set_softwareversion(version, "softwareversion");
	//osync_version_set_hardwareversion(version, "hardwareversion");
	osync_plugin_info_set_version(info, version);
	osync_version_unref(version);

	osync_trace(TRACE_EXIT, "%s", __func__);
	return TRUE;
}
static OSyncObjTypeSink *find_sink(const char *objtype, OSyncError **error)
{
	OSyncObjTypeSink *sink = NULL;
	assert(objtype);

	sink = osync_plugin_info_find_objtype(plugin_info, objtype);
	if (!sink) {
		osync_error_set(error, OSYNC_ERROR_GENERIC, "Unable to find sink for %s", objtype);
		return NULL;
	}

	return sink;
}
/* Here we actually tell opensync which sinks are available. For this plugin, we
 * go through the list of directories and enable all, since all have been configured */
static osync_bool mock_discover(OSyncPluginInfo *info, void *data, OSyncError **error)
{
	osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, error);

	OSyncPluginConfig *config = osync_plugin_info_get_config(info);
	osync_assert_msg(config, "No OSyncPluginConfig set for mock_discover!");

	/*
	OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info);
	osync_assert_msg(config, "No OSyncFormatEnv set for mock_discover!");
	*/

	OSyncList *r = osync_plugin_config_get_resources(config);
	for (; r; r = r->next) {
		OSyncPluginResource *res = r->data;
		OSyncObjTypeSink *sink;

		const char *objtype = osync_plugin_resource_get_objtype(res);
		/* Check for ObjType sink */
		if ((sink = osync_plugin_info_find_objtype(info, objtype)))
			osync_objtype_sink_set_available(sink, TRUE);
 	}


	OSyncVersion *version = osync_version_new(error);
	osync_version_set_plugin(version, "mock-sync");
	//osync_version_set_vendor(version, "version");
	//osync_version_set_modelversion(version, "version");
	//osync_version_set_firmwareversion(version, "firmwareversion");
	//osync_version_set_softwareversion(version, "softwareversion");
	//osync_version_set_hardwareversion(version, "hardwareversion");
	osync_plugin_info_set_version(info, version);
	osync_version_unref(version);

	/* we can set here the capabilities, but for the file-sync
	 * plugin they are static and shipped with opensync */


	if (mock_get_error(info->memberid, "MOCK_DISCOVER_ERROR")) {
		osync_error_set(error, OSYNC_ERROR_EXPECTED, "MOCK_DISCOVER_ERROR on purpose!");
		osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
		return FALSE;
	}

	osync_trace(TRACE_EXIT, "%s", __func__);
	return TRUE;
}
static osync_bool init(OSyncError **error) {
	OSyncPluginConfig *config;
	assert(!plugin);
	assert(!plugin_env);

	if (!(plugin_env = osync_plugin_env_new(error)))
		goto error;

	if (!(format_env = osync_format_env_new(error)))
		goto error_free_pluginenv;

	if (!osync_format_env_load_plugins(format_env, formatpath, error))
		goto error_free_formatenv;

	if (osync_error_is_set(error)) {
		fprintf(stderr, "WARNING! Some plugins couldn't get loaded in "
				"format plugin environment: %s\n", osync_error_print(error));
		osync_error_unref(error);
	}

	if (!osync_plugin_env_load(plugin_env, pluginpath, error))
		goto error_free_pluginenv;

	if (osync_error_is_set(error)) {
		fprintf(stderr, "WARNING! Some plugins couldn't get loaded in "
				"plugin environment: %s\n", osync_error_print(error));
		osync_error_unref(error);
	}

	if (!(plugin = osync_plugin_env_find_plugin(plugin_env, pluginname))) {
		osync_error_set(error, OSYNC_ERROR_PLUGIN_NOT_FOUND, "Plugin not found: \"%s\"", pluginname);
		goto error_free_pluginenv;
	}

	if (!(plugin_info = osync_plugin_info_new(error)))
		goto error_free_pluginenv;

	config = osync_plugin_config_new(error);
	if (!config)
		goto error_free_plugininfo;

	if (osync_plugin_get_config_type(plugin) != OSYNC_PLUGIN_NO_CONFIGURATION && configfile) {
		OSyncList *r = NULL;
		if (!osync_plugin_config_file_load(config, configfile, error))
			goto error_free_pluginconfig;

		osync_plugin_info_set_config(plugin_info, config);

		/** Redudant(aka. stolen) code from opensync/client/opensync_client.c */
		/* Enable active sinks */

		if (config)
			r = osync_plugin_config_get_resources(config);

		for (; r; r = r->next) {
			OSyncPluginResource *res = r->data;
			OSyncObjTypeSink *sink;

			const char *objtype = osync_plugin_resource_get_objtype(res); 
			OSyncList *o = NULL;
			/* Check for ObjType sink */
			if (!(sink = osync_plugin_info_find_objtype(plugin_info, objtype))) {
				sink = osync_objtype_sink_new(objtype, error);
				if (!sink)
					goto error_free_pluginconfig;

				osync_plugin_info_add_objtype(plugin_info, sink);
			}
			OSyncList *objformats = osync_plugin_resource_get_objformat_sinks(res);
			for ( o = objformats; o; o = o->next) {
				OSyncObjFormatSink *format_sink = (OSyncObjFormatSink *) o->data; 
				osync_objtype_sink_add_objformat_sink(sink, format_sink);
			}
			osync_list_free(objformats);
		}

		osync_plugin_config_unref(config);

	}

	if (!configfile && osync_plugin_get_config_type(plugin) == OSYNC_PLUGIN_NEEDS_CONFIGURATION) {
		osync_error_set(error, OSYNC_ERROR_MISCONFIGURATION, "Plugin \"%s\" requires configuration!", pluginname); 
		goto error_free_pluginconfig;
	}

	assert(!ctx);
	ctx = g_main_context_new();

	osync_plugin_info_set_configdir(plugin_info, configdir);
	osync_plugin_info_set_loop(plugin_info, ctx);
	osync_plugin_info_set_format_env(plugin_info, format_env);
	osync_plugin_info_set_groupname(plugin_info, syncgroup);

	return TRUE;

	/*
		error_free_loop:
		g_main_context_unref(ctx);
	*/
 error_free_pluginconfig:
	osync_plugin_config_unref(config);
 error_free_plugininfo:
	osync_plugin_info_unref(plugin_info);
 error_free_formatenv:
	osync_format_env_unref(format_env);
	format_env = NULL;
 error_free_pluginenv:
	osync_plugin_env_unref(plugin_env);
	plugin_env = NULL;
 error:	
	return FALSE;
}