/* gcc $(pkg-config --cflags --libs libgdata goa-1.0 gio-2.0 glib-2.0)
   gdata-query.c */

#include <gio/gio.h>
#include <glib.h>

#define GOA_API_IS_SUBJECT_TO_CHANGE
#include <gdata/gdata.h>
#include <goa/goa.h>

static void
download_stream (GInputStream *src, const gchar *dest)
{
  GFile *file;
  GFileOutputStream *ostream = NULL;

  file = g_file_new_for_path (dest);
  ostream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, NULL);
  g_output_stream_splice (G_OUTPUT_STREAM (ostream),
                          G_INPUT_STREAM (src),
                          G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                          NULL,
                          NULL);
  g_clear_object (&ostream);
}

static void
show_entry (GDataDocumentsService *service, GDataEntry *entry)
{
  GDataFeed *feed = NULL;
  GDataLink *link;
  GError *error = NULL;
  GList *authors;
  GList *categories;
  GList *entries;
  GList *k;
  GList *links = NULL;
  const gchar *document_id;
  const gchar *etag;
  const gchar *id;
  const gchar *resource_id;
  const gchar *summary;
  const gchar *title;
  const gchar *uri;
  gint64 edited;
  gint64 last_viewed;
  gint64 published;
  gint64 updated;
  goffset quota_used;

  id = gdata_entry_get_id (entry);
  g_message ("id: %s", id);

  g_message ("type: %s", G_OBJECT_TYPE_NAME (entry));

  document_id = gdata_documents_entry_get_document_id (GDATA_DOCUMENTS_ENTRY (entry));
  resource_id = gdata_documents_entry_get_resource_id (GDATA_DOCUMENTS_ENTRY (entry));
  g_message ("document_id: %s, resource_id: %s", document_id, resource_id);

  title = gdata_entry_get_title (entry);
  g_message ("title: %s", title);

  uri = gdata_entry_get_content_uri (entry);
  g_message ("content uri: %s", uri);

  if (GDATA_IS_DOCUMENTS_DOCUMENT (entry))
    {
      uri = gdata_documents_document_get_thumbnail_uri (GDATA_DOCUMENTS_DOCUMENT (entry));
      g_message ("thumbnail uri: %s", uri);
    }

  etag = gdata_entry_get_etag (entry);
  g_message ("etag: %s", etag);

  published = gdata_entry_get_published (entry);
  last_viewed = gdata_documents_entry_get_last_viewed (GDATA_DOCUMENTS_ENTRY (entry));
  g_message ("published: %" G_GINT64_FORMAT ", last viewed: %" G_GINT64_FORMAT, published, last_viewed);

  edited = gdata_documents_entry_get_edited (GDATA_DOCUMENTS_ENTRY (entry));
  updated = gdata_entry_get_updated (entry);
  g_message ("edited: %" G_GINT64_FORMAT ", updated: %" G_GINT64_FORMAT, edited, updated);

  quota_used = gdata_documents_entry_get_quota_used (GDATA_DOCUMENTS_ENTRY (entry));
  g_message ("quota used: %" G_GOFFSET_FORMAT, quota_used);

  link = gdata_entry_look_up_link (entry, GDATA_LINK_SELF);
  uri = gdata_link_get_uri (link);
  g_message ("self: %s", uri);

  link = gdata_entry_look_up_link (entry, GDATA_LINK_ALTERNATE);
  uri = gdata_link_get_uri (link);
  g_message ("alternate: %s", uri);

  links = gdata_entry_look_up_links (entry, "http://schemas.google.com/docs/2007#parent");
  for (k = links; k != NULL; k = k->next)
    {
      link = GDATA_LINK (k->data);
      uri = gdata_link_get_uri (link);
      g_message ("parent: %s", uri);
    }

  categories = gdata_entry_get_categories (entry);
  for (k = categories; k != NULL; k = k->next)
    {
      GDataCategory *category = GDATA_CATEGORY (k->data);
      const gchar *label;
      const gchar *scheme;
      const gchar *term;

      scheme = gdata_category_get_scheme (category);
      g_message ("scheme: %s", scheme);

      term = gdata_category_get_term (category);
      g_message ("term: %s", term);

      label = gdata_category_get_label (category);
      g_message ("label: %s", label);
    }

  summary = gdata_entry_get_summary (GDATA_ENTRY (entry));
  g_message ("summary: %s", summary);

  authors = gdata_entry_get_authors (GDATA_ENTRY (entry));
  for (k = authors; k != NULL; k = k->next)
    {
      GDataAuthor *author = GDATA_AUTHOR (k->data);
      const gchar *email;
      const gchar *name;

      email = gdata_author_get_email_address (author);
      name = gdata_author_get_name (author);
      g_message ("email: %s, name: %s", email, name);

      uri = gdata_author_get_uri (author);
      g_message ("uri: %s", uri);
    }

  feed = gdata_access_handler_get_rules (GDATA_ACCESS_HANDLER (entry),
                                         GDATA_SERVICE (service),
                                         NULL,
                                         NULL, NULL, &error);
  if (error != NULL)
    {
      g_warning ("get-rules: (%s): %s", g_quark_to_string (error->domain), error->message);
      g_error_free (error);
      goto out;
    }

  entries = gdata_feed_get_entries (feed);
  for (k = entries; k != NULL; k = k->next)
    {
      GDataAccessRule *rule = GDATA_ACCESS_RULE (k->data);
      const gchar *key;
      const gchar *role;
      const gchar *scope_type;
      const gchar *scope_value;
      gint64 edited;

      key = gdata_access_rule_get_key (rule);
      g_message ("key: %s", key);

      role = gdata_access_rule_get_role (rule);
      g_message ("role: %s", role);

      gdata_access_rule_get_scope (rule, &scope_type, &scope_value);
      g_message ("scope_type: %s, scope_value: %s", scope_type, scope_value);

      edited = gdata_access_rule_get_edited (rule);
      g_message ("edited: %" G_GINT64_FORMAT, edited);
    }

 out:
  g_clear_object (&feed);
  g_list_free (links);
}

gint
main (void)
{
  GDataDocumentsFeed *documents_feed = NULL;
  GDataDocumentsQuery *query = NULL;
  GDataDocumentsService *service = NULL;
  GError *error = NULL;
  GList *accounts = NULL;
  GList *l;
  GoaClient *client = NULL;

  client = goa_client_new_sync (NULL, &error);
  if (error != NULL)
    {
      g_warning ("%s", error->message);
      g_error_free (error);
      goto out;
    }

  accounts = goa_client_get_accounts (client);
  for (l = accounts; l != NULL; l = l->next)
    {
      GoaAccount *account;
      GoaObject *object = GOA_OBJECT (l->data);
      const gchar *account_identity;
      const gchar *provider_type;

      account = goa_object_peek_account (object);
      account_identity = goa_account_get_identity (account);
      provider_type = goa_account_get_provider_type (account);

      if (g_strcmp0 (provider_type, "google") == 0)
        {
          GDataGoaAuthorizer *authorizer;

          authorizer = gdata_goa_authorizer_new (object);
          service = gdata_documents_service_new (GDATA_AUTHORIZER (authorizer));
          g_object_unref (authorizer);
        }
    }

  if (service == NULL)
    {
      g_warning ("account not found");
      goto out;
    }

  query = gdata_documents_query_new_with_limits (NULL, 1, 10);
  gdata_documents_query_set_show_folders (query, TRUE);

  while (TRUE)
    {
      GDataLink *link;
      GList *document_entries;
      const gchar *uri;

      error = NULL;
      documents_feed = gdata_documents_service_query_documents (service, query, NULL, NULL, NULL, &error);
      if (error != NULL)
        {
          g_warning ("query-documents: (%s): %s", g_quark_to_string (error->domain), error->message);
          g_error_free (error);
          goto out;
        }

      link = gdata_feed_look_up_link (GDATA_FEED (documents_feed), GDATA_LINK_SELF);
      uri = gdata_link_get_uri (link);
      g_message ("self: %s", uri);

      g_message ("======");
      g_message ("======");

      document_entries = gdata_feed_get_entries (GDATA_FEED (documents_feed));
      if (document_entries == NULL)
        goto out;

      for (l = document_entries; l != NULL; l = l->next)
        {
          GDataAuthorizationDomain *domain;
          GDataEntry *entry = GDATA_ENTRY (l->data);
          const gchar *id;

          show_entry (service, entry);
          g_message ("......");

          id = gdata_entry_get_id (entry);
          entry = NULL;

          domain = gdata_documents_service_get_primary_authorization_domain ();

          error = NULL;
          entry = gdata_service_query_single_entry (GDATA_SERVICE (service),
                                                    domain,
                                                    id,
                                                    NULL,
                                                    GDATA_TYPE_DOCUMENTS_TEXT,
                                                    NULL,
                                                    &error);
          if (error != NULL)
            {
              g_warning ("query-single-entry: (%s): %s", g_quark_to_string (error->domain), error->message);
              g_error_free (error);
              goto continuation;
            }

          show_entry (service, entry);

          g_message ("======");
          g_message ("======");

          if (g_strcmp0 (id, "1T4Z2q7q_0fa-qdFqIpCQVNYe78RLNS0UqhMRgY1ixGs") == 0)
            {
              GDataDownloadStream *istream = NULL;

              error = NULL;
              istream = gdata_documents_document_download (GDATA_DOCUMENTS_DOCUMENT (entry), service, "pdf", NULL, &error);
              if (error != NULL)
                {
                  g_warning ("download: (%s): %s", g_quark_to_string (error->domain), error->message);
                  g_error_free (error);
                  goto continuation;
                }

              download_stream (G_INPUT_STREAM (istream), "/tmp/gnome-online.pdf");
              g_object_unref (istream);
            }

          if (g_strcmp0 (id, "0B9J_DkaiBDRFZzVsNDBOMzZBM2c") == 0)
            {
              GInputStream *istream;
              const gchar *uri;

              uri = gdata_documents_document_get_thumbnail_uri (GDATA_DOCUMENTS_DOCUMENT (entry));
              istream = gdata_download_stream_new (GDATA_SERVICE (service), domain, uri, NULL);
              download_stream (G_INPUT_STREAM (istream), "/tmp/thumbnail-three-birds.jpg");
              g_object_unref (istream);

              uri = gdata_entry_get_content_uri (entry);
              istream = gdata_download_stream_new (GDATA_SERVICE (service), domain, uri, NULL);
              download_stream (G_INPUT_STREAM (istream), "/tmp/three-birds.jpg");
              g_object_unref (istream);
            }

        continuation:
          g_clear_object (&entry);
        }

      g_message ("next page...");
      gdata_query_next_page (GDATA_QUERY (query));
      g_object_unref (documents_feed);
    }

 out:
  g_clear_object (&documents_feed);
  g_clear_object (&query);
  g_clear_object (&service);
  g_clear_object (&client);
  g_list_free_full (accounts, g_object_unref);
  return 0;
}
