
#include "frost_common.h"
#include "frost_str.h"
#include "frost_mem.h"
#include "ice_streamer.h"

#include "utilities_debug/cabot_assert.h"
#include "utilities_debug/trace.h"

TRACE_IMPLEMENT("ice/ice_streamer_outputplugin");

static void
destroy (ice_streamer_object_t *obj)
{
    ice_streamer_handler_plugin_t *plugin = (ice_streamer_handler_plugin_t *) obj;

    while (plugin->in_types) {
        ice_streamer_object_unref (plugin->in_types->data);

        plugin->in_types = frost_list_delete_link (plugin->in_types,
                                               plugin->in_types);
    }

    ice_streamer_plugin_destroy ((ice_streamer_plugin_t *) obj);
}

ice_streamer_handler_plugin_t *
ice_streamer_handler_plugin_new (void)
{
    ice_streamer_handler_plugin_t *res;

    res = ice_streamer_object_new (ice_streamer_handler_plugin_t, destroy);

    return (ice_streamer_handler_plugin_t *)res;
}

void
ice_streamer_handler_plugin_methods_set (ice_streamer_handler_plugin_t *plugin,
                               ice_streamer_handler_methods_t *methods)
{
    frost_return_if_fail (plugin);
    frost_return_if_fail (plugin->plugin.type == ICE_PLUGIN_TYPE_XFORM);

    TRACE_INFO(("Registering xform '%s'",
            ice_streamer_plugin_shortname_get ((ice_streamer_plugin_t *) plugin)));

    memcpy (&plugin->methods, methods, sizeof (ice_streamer_handler_methods_t));
}

frost_bool
ice_streamer_handler_plugin_verify (ice_streamer_handler_plugin_t *_plugin)
{
    ice_streamer_handler_plugin_t *plugin = (ice_streamer_handler_plugin_t *) _plugin;

    frost_return_val_if_fail (plugin, frost_false);
    frost_return_val_if_fail (plugin->plugin.type == ICE_PLUGIN_TYPE_XFORM, frost_false);

    /* more checks */

    return frost_true;
}

void
ice_streamer_handler_plugin_indata_add (ice_streamer_handler_plugin_t *plugin, ...)
{
    ice_streamer_stream_type_t *t;
    va_list ap;
    char *config_key, config_value[32];
    frost_int priority;

    va_start (ap, plugin);
    t = ice_streamer_stream_type_parse (ap);
    va_end (ap);

    config_key = frost_strconcat ("priority.",
            ice_streamer_stream_type_get_str (t, ICE_STREAM_TYPE_NAME),
                              NULL);
    priority = ice_streamer_stream_type_get_int (t, ICE_STREAM_TYPE_PRIORITY);
    frost_snprintf (config_value, sizeof (config_value), "%d", priority);
    ice_streamer_handler_plugin_config_property_register (plugin, config_key,
                                                config_value, NULL, NULL);
    frost_free (config_key);

    plugin->in_types = frost_list_prepend (plugin->in_types, t);
}

frost_bool
ice_streamer_handler_plugin_supports (const ice_streamer_handler_plugin_t *plugin, ice_streamer_stream_type_t *st,
                            frost_int *priority)
{
    FROST_List *t;

    frost_return_val_if_fail (st, frost_false);
    frost_return_val_if_fail (plugin, frost_false);
    frost_return_val_if_fail (priority, frost_false);

    for (t = plugin->in_types; t; t = frost_list_next (t)) {
        ice_streamer_config_property_t *config_priority;
        const char *type_name;
        char *config_key;

        if (!ice_streamer_stream_type_match ((const ice_streamer_stream_type_t *)t->data, st)) {
            continue;
        }

        type_name = ice_streamer_stream_type_get_str ((const ice_streamer_stream_type_t *)t->data, ICE_STREAM_TYPE_NAME);

        config_key = frost_strconcat ("priority.", type_name, NULL);
        config_priority = ice_streamer_plugin_config_lookup ((ice_streamer_plugin_t *) plugin,
                                                     config_key);
        frost_free (config_key);

        if (config_priority) {
            *priority = ice_streamer_config_property_get_int (config_priority);
        } else {
            *priority = ICE_STREAM_TYPE_PRIORITY_DEFAULT;
        }

        return frost_true;
    }

    return frost_false;
}

ice_streamer_config_property_t *
ice_streamer_handler_plugin_config_property_register (ice_streamer_handler_plugin_t *xform_plugin,
                                            const char *name,
                                            const char *default_value,
                                            ice_streamer_object_handler_t cb,
                                            frost_pointer userdata)
{
    ice_streamer_plugin_t *plugin =  (ice_streamer_plugin_t *)xform_plugin;

    return ice_streamer_plugin_config_property_register (plugin, name,
                                                 default_value,
                                                 cb, userdata);
}

frost_bool
ice_streamer_handler_plugin_can_init (const ice_streamer_handler_plugin_t *plugin)
{
    return (!!plugin->methods.init) ? frost_true : frost_false;
}

frost_bool
ice_streamer_handler_plugin_can_read (const ice_streamer_handler_plugin_t *plugin)
{
    return (!!plugin->methods.read) ? frost_true : frost_false;
}

frost_bool
ice_streamer_handler_plugin_can_seek (const ice_streamer_handler_plugin_t *plugin)
{
    return (!!plugin->methods.seek) ? frost_true : frost_false;
}

frost_bool
ice_streamer_handler_plugin_can_browse (const ice_streamer_handler_plugin_t *plugin)
{
    return (!!plugin->methods.browse) ? frost_true : frost_false;
}

frost_bool
ice_streamer_handler_plugin_can_destroy (const ice_streamer_handler_plugin_t *plugin)
{
    return (!!plugin->methods.destroy) ? frost_true : frost_false;
}

frost_bool
ice_streamer_handler_plugin_init (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform)
{
    return plugin->methods.init (xform);
}

frost_int
ice_streamer_handler_plugin_read (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                        ice_sample_t *buf, frost_int length, ice_error_code_t *error)
{
    return plugin->methods.read (xform, buf, length, error);
}

frost_int64
ice_streamer_handler_plugin_seek (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                        frost_int64 offset, ice_seek_mode_t whence,
                        ice_error_code_t *err)
{
    return plugin->methods.seek (xform, offset, whence, err);
}


frost_bool
ice_streamer_handler_plugin_browse (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform,
                          const char *url, ice_error_code_t *error)
{
    return plugin->methods.browse (xform, url, error);
}

void
ice_streamer_handler_plugin_destroy (const ice_streamer_handler_plugin_t *plugin, ice_streamer_handler_t *xform)
{
    plugin->methods.destroy (xform);
}

