#include <glib.h>

#include <telepathy-logger/log-manager.h>
#include <telepathy-logger/text-event.h>
#include <telepathy-logger/call-event.h>

#define SCOLE_CALL_LOG_MAX_EVENTS       100


TpAccountManager *account_manager;
TplLogManager *log_manager;
GList *accounts;

static const gchar*
_get_entity_name (TplEntity *e)
{
    const gchar* stype = "";
    TplEntityType etype = tpl_entity_get_entity_type (e);
    if (etype == TPL_ENTITY_CONTACT) {
        stype = "Contact";
    } else if (etype == TPL_ENTITY_ROOM) {
        stype = "Room";
    } else if (etype == TPL_ENTITY_SELF) {
        stype = "Self";
    } else {
        stype = "Unknown";
    }
    return stype;
}

static void
_call_log_on_filter_done (TplLogManager *source, GAsyncResult *res, gpointer data)
{
    g_debug("%s", G_STRFUNC);
    GError *error = NULL;
    GList *events = NULL;

    if (!tpl_log_manager_get_filtered_events_finish (source, res, &events, &error)) {
        g_debug ("Fail to get events: %s", error->message);
        g_error_free (error);
        return;
    }

    TplEntity *e = (TplEntity*) data;


    g_debug ("Entity(%s): %s - Size: %d",
             _get_entity_name (e),
             tpl_entity_get_identifier (e),
             g_list_length (events));

    GList *walk = events;
    for(; walk; walk = walk->next) {
        TplEvent *event = (TplEvent*) walk->data;
        gint64 timestamp = tpl_event_get_timestamp (event);
        TplEntity *sender = tpl_event_get_sender (event);
        TplEntity *receiver = tpl_event_get_receiver (event);


        g_debug ("EVENT (%s): %ld", TPL_IS_CALL_EVENT(event) ? "Call" : "Text", timestamp);
        g_debug ("\tSENDER (%s):", _get_entity_name (sender));
        g_debug ("\t\tID: [%s]", tpl_entity_get_identifier (sender));
        g_debug ("\t\tALIAS: [%s]", tpl_entity_get_alias (sender));

        g_debug ("\tRECEIVER (%s):", _get_entity_name (receiver));
        g_debug ("\t\tID: [%s]", tpl_entity_get_identifier (receiver));
        g_debug ("\t\tALIAS: [%s]", tpl_entity_get_alias (receiver));

        if (TPL_IS_TEXT_EVENT (event)) {
            g_debug ("\tEDIT TIMESTAMP (%ld):", tpl_text_event_get_edit_timestamp ( (TplTextEvent *) event));
            g_debug ("\tMESSAGE TOKEN: %s", tpl_text_event_get_message_token( (TplTextEvent *) event));
        }
    }
}

static gboolean
_call_log_filter_events (TplEvent *event,
                         gpointer data)
{
    return TRUE;
}


static void
_call_log_get_entities_done (TplLogManager *source,
                             GAsyncResult *res,
                             TpAccount *account)
{
    g_debug("%s", G_STRFUNC);

    GList *entities = NULL;
    GError *error = NULL;

    if (!tpl_log_manager_get_entities_finish (source, res, &entities, &error)) {
        g_warning ("Fail to get entities related with account: %s", error->message);
        g_error_free (error);
        return;
    }

    GList *walk = entities;
    for (; walk; walk = walk->next) {
        tpl_log_manager_get_filtered_events_async (log_manager,
                                                   account,
                                                   (TplEntity*) walk->data,
                                                   TPL_EVENT_MASK_CALL | TPL_EVENT_MASK_TEXT,
                                                   SCOLE_CALL_LOG_MAX_EVENTS,
                                                   (TplLogEventFilter) _call_log_filter_events,
                                                   NULL,
                                                   (GAsyncReadyCallback) _call_log_on_filter_done,
                                                   walk->data);
    }
}

static void
_list_all_logs ()
{
    g_debug("%s", G_STRFUNC);
    GList *walk;
    walk = accounts;
    for(; walk; walk = walk->next) {
        tpl_log_manager_get_entities_async (log_manager,
                                            walk->data,
                                            (GAsyncReadyCallback) _call_log_get_entities_done,
                                            walk->data);
    }
}

static void
_call_log_setup ()
{
    g_debug("%s", G_STRFUNC);
    log_manager = tpl_log_manager_dup_singleton ();
    _list_all_logs ();
}

static void
_account_manager_prepared (TpAccountManager *mng, GAsyncResult *res, gpointer data)
{
    g_debug("%s", G_STRFUNC);
    GError *error = NULL;


    tp_proxy_prepare_finish (mng, res, &error);
    if (error) {
        g_debug ("Account manager error: %s", error->message);
        g_error_free (error);
    } else {
        accounts = tp_account_manager_get_valid_accounts (mng);
        if (accounts) {
            _call_log_setup ();
        } else {
            g_warning ("No valid accounts");
        }
    }
}

static void
_call_log_run ()
{
    g_debug("%s", G_STRFUNC);
    if (!account_manager) {
        account_manager = tp_account_manager_dup ();
    }

    tp_proxy_prepare_async (account_manager,
                            NULL,
                            (GAsyncReadyCallback) _account_manager_prepared,
                            NULL);
}

void
main (int argc, char** argv)
{
    g_type_init ();

    GMainLoop *loop = g_main_loop_new (NULL, FALSE);

    account_manager = NULL;
    log_manager = NULL;
    accounts = NULL;

    _call_log_run ();

    //g_timeout_add (10 * 1000, g_main_loop_quit, loop);
    g_main_loop_run (loop);
}
