#include <stdio.h>
#include <stdlib.h>

#include <glib.h>
#include <glib-object.h>
#include <glib/gstdio.h>

#include "apt-cache-parser.h"
#include "unity-webapps-url-db.h"

#include "../unity-webapps-debug.h"

static GMainLoop *main_loop = NULL;
static AptCacheParser *parser = NULL;
static UnityWebappsUrlDB *url_db = NULL;

#define UNITY_WEBAPPS_APT_CACHE_BINARY_ENV_VARIABLE "UNITY_WEBAPPS_APT_CACHE_BINARY"

gboolean
spawn_apt_cache (GIOChannel **available, GError **error)
{
  const gchar *argv[] = {"apt-cache", "dumpavail", NULL};
  const gchar *envbinary;
  gint cstdo;
  
  envbinary = g_getenv (UNITY_WEBAPPS_APT_CACHE_BINARY_ENV_VARIABLE);
  if (envbinary != NULL)
    {
      argv[0] = envbinary;
    }
  
  g_spawn_async_with_pipes (NULL, (gchar **)argv, NULL,
			    G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL,
			    &cstdo, NULL, error);
  
  *available = NULL;
  
  if (*error != NULL)
    {
      g_warning ("Failed to spawn apt-cache: %s\n", (*error)->message);
      return FALSE;
    }
  
  *available = g_io_channel_unix_new (cstdo);
		
  return TRUE;
}

gboolean
package_info_available (GIOChannel *channel,
			GIOCondition condition,
			gpointer user_data)
{
  gchar *line;
  GIOStatus ret;
  
  ret = G_IO_STATUS_NORMAL;

  while (ret == G_IO_STATUS_NORMAL)
    {
      ret = g_io_channel_read_line (channel, &line, NULL, NULL, NULL);

      if (line != NULL)
	{
	  apt_cache_parser_next_line (parser, line);
	}
    }
  return TRUE;
}

gboolean
package_info_done (GIOChannel *channel,
		   GIOCondition condition,
		   gpointer user_data)
{
  GList *infos;
  
  infos= apt_cache_parser_get_webapp_infos (parser);
  
  while (infos != NULL)
    {
      WebappInfo *info;
      GPtrArray *urls;
      const gchar *package_name;
      const gchar *application_name;
      const gchar *application_domain; 
      int i;
      UnityWebappsUrlDBRecord *record;

      info = (WebappInfo *)infos->data;
      
      package_name = webapp_info_get_package_name (info);
      infos = infos->next;
      
      application_name = webapp_info_get_application_name (info);
      application_domain = webapp_info_get_application_domain (info);
      UNITY_WEBAPPS_NOTE (INDEX_UPDATER, "Found webapp: %s (%s, %s)\n", package_name, application_name, application_domain);

      
      urls = webapp_info_get_urls (info);
      
      record = unity_webapps_url_db_record_new (package_name, application_name, application_domain);
      
      for (i = 0; i < urls->len; i++)
	{
	  gchar *url;
	  
	  url = (gchar *)g_ptr_array_index (urls, i);
	  unity_webapps_url_db_insert_url (url_db, url, record);
	}
      
      unity_webapps_url_db_record_free (record);
    }
  
  g_main_loop_quit (main_loop);
  return FALSE;
}

gboolean
list_available_webapps ()
{
  GIOChannel *available;
  GError *error;
  gboolean spawned;
  
  error = NULL;
  
  spawned = spawn_apt_cache (&available, &error);
  
  if (spawned == FALSE)
    {
      g_error ("Error listing available packages: %s \n", error->message);
      g_error_free (error);
      
      return FALSE;
    }
  
  parser = apt_cache_parser_new ();
  
  
  
  g_io_add_watch (available, G_IO_IN, package_info_available, parser);
  g_io_add_watch (available, G_IO_HUP, package_info_done, NULL);
  
  return TRUE;
}

int
main (gint argc, gchar **argv)
{
  url_db = unity_webapps_url_db_open_default (FALSE);

  if (!url_db)
    {
      g_critical ("can't access URL DB");
      return 1;
    }

  list_available_webapps();

  main_loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (main_loop);

  return 0;
}
