/*
 * unity-webapps-local-available-application.c
 * Copyright (C) Canonical LTD 2011
 *
 * Author: Robert Carr <racarr@canonical.com>
 * 
 unity-webapps is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * unity-webapps is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.";
 */

/* This object is to encapsulate the userscript script loading abstractions as opposed to the manifest contents */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <glib/gstdio.h>
#include <gio/gio.h>

#include "unity-webapps-local-available-application.h"

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

struct _UnityWebappsLocalAvailableApplicationPrivate {
  UnityWebappsApplicationManifest *manifest;
  
  GList *pattern_specs;
};

enum {
  PROP_0,
  PROP_MANIFEST
};




G_DEFINE_TYPE(UnityWebappsLocalAvailableApplication, unity_webapps_local_available_application, UNITY_WEBAPPS_TYPE_AVAILABLE_APPLICATION)

#define UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), UNITY_WEBAPPS_TYPE_LOCAL_AVAILABLE_APPLICATION, UnityWebappsLocalAvailableApplicationPrivate))

static void
unity_webapps_local_available_application_get_property (GObject *object,
					     guint prop_id,
					     GValue *value,
					     GParamSpec *pspec)
{
  UnityWebappsLocalAvailableApplication *app;
  
  app = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (object);
  
  switch (prop_id)
    {
    case PROP_MANIFEST:
      g_value_set_object (value, app->priv->manifest);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
unity_webapps_local_available_application_set_property (GObject *object,
						       guint prop_id,
						       const GValue *value,
						       GParamSpec *pspec)
{
  UnityWebappsLocalAvailableApplication *app;
  
  app = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (object);
  
  switch (prop_id)
    {
    case PROP_MANIFEST:
      g_return_if_fail (app->priv->manifest == NULL);
      app->priv->manifest = g_value_dup_object (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
local_available_application_get_is_installed (UnityWebappsAvailableApplication *available_application,
					     UnityWebappsAvailableApplicationInstalledQueryCallback callback,
					     gpointer user_data)
{
  callback(available_application, TRUE, user_data);
}

static const gchar *
local_available_application_get_name (UnityWebappsAvailableApplication *available_application)
{
  UnityWebappsLocalAvailableApplication *self;
  
  self = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (available_application);
  
  return unity_webapps_application_manifest_get_package_name (self->priv->manifest);
}

static const gchar *
local_available_application_get_application_name (UnityWebappsAvailableApplication *available_application)
{
  UnityWebappsLocalAvailableApplication *self;
  
  self = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (available_application);
  
  return unity_webapps_application_manifest_get_name (self->priv->manifest);
}

static const gchar *
local_available_application_get_application_domain (UnityWebappsAvailableApplication *available_application)
{
  UnityWebappsLocalAvailableApplication *self;
  
  self = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (available_application);
  
  return unity_webapps_application_manifest_get_domain (self->priv->manifest);
}

static void
unity_webapps_local_available_application_finalize (GObject *object)
{
  UnityWebappsLocalAvailableApplication *self;
  
  self = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION (object);

  if (self->priv->manifest)
    {
      g_object_unref (G_OBJECT (self->priv->manifest));
    }
  
  if (self->priv->pattern_specs)
    {
      GList *l;
      
      l = self->priv->pattern_specs;
      
      while (l != NULL)
	{
	  GPatternSpec *pspec;
	  pspec = (GPatternSpec *)l->data;
	  
	  g_pattern_spec_free (pspec);

	  l = l->next;
	}
    }
}

static void
unity_webapps_local_available_application_class_init (UnityWebappsLocalAvailableApplicationClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  UnityWebappsAvailableApplicationClass *available_application_class = UNITY_WEBAPPS_AVAILABLE_APPLICATION_CLASS (klass);
  
  object_class->finalize = unity_webapps_local_available_application_finalize;
  object_class->get_property = unity_webapps_local_available_application_get_property;
  object_class->set_property = unity_webapps_local_available_application_set_property;

  available_application_class->get_name = local_available_application_get_name;
  available_application_class->get_application_name = local_available_application_get_application_name;
  available_application_class->get_application_domain = local_available_application_get_application_domain;
  available_application_class->get_is_installed = local_available_application_get_is_installed;
  
  g_type_class_add_private (object_class, sizeof(UnityWebappsLocalAvailableApplicationPrivate));

  g_object_class_install_property (object_class, PROP_MANIFEST,
				   g_param_spec_object ("manifest",
							"Mame",
							"The Application Manifest",
							UNITY_WEBAPPS_TYPE_APPLICATION_MANIFEST,
							G_PARAM_READWRITE | 
							G_PARAM_STATIC_STRINGS |
							G_PARAM_CONSTRUCT_ONLY));
 
}

static void
unity_webapps_local_available_application_init (UnityWebappsLocalAvailableApplication *self)
{
  self->priv = UNITY_WEBAPPS_LOCAL_AVAILABLE_APPLICATION_GET_PRIVATE (self);
  
  self->priv->manifest = NULL;
  self->priv->pattern_specs = NULL;
}



UnityWebappsAvailableApplication *
unity_webapps_local_available_application_new (UnityWebappsApplicationManifest *manifest)
{
  return UNITY_WEBAPPS_AVAILABLE_APPLICATION (g_object_new (UNITY_WEBAPPS_TYPE_LOCAL_AVAILABLE_APPLICATION, "manifest", manifest, NULL));
}

UnityWebappsApplicationManifest *
unity_webapps_local_available_application_get_manifest (UnityWebappsLocalAvailableApplication *app)
{
  return app->priv->manifest;
}

static gboolean
unity_webapps_local_available_application_compile_pattern_specs (UnityWebappsLocalAvailableApplication *app)
{
  const gchar **includes;
  gint length, i;

  g_return_val_if_fail (app->priv->manifest != NULL, FALSE);
  g_return_val_if_fail (app->priv->pattern_specs == NULL, FALSE);
  
  includes = unity_webapps_application_manifest_get_includes (app->priv->manifest);
  
  length = g_strv_length ((gchar **)includes);
  for (i = 0; i < length; i++)
    {
      GPatternSpec *spec;
      const gchar *include;

      include = includes[i];
      
      spec = g_pattern_spec_new (include);
      app->priv->pattern_specs = g_list_append (app->priv->pattern_specs, spec);
    }
  return TRUE;
}

gboolean
unity_webapps_local_available_application_provides_url (UnityWebappsLocalAvailableApplication *application, const gchar *url)
{
  GList *w;
  
  if (application->priv->pattern_specs == NULL)
    {
      unity_webapps_local_available_application_compile_pattern_specs (application);
    }
  
  for (w = application->priv->pattern_specs; w != NULL; w = w->next)
    {
      GPatternSpec *pspec;
      gboolean matched;
      
      pspec = (GPatternSpec *)w->data;
      matched = g_pattern_match_string (pspec, url);
      if (matched == TRUE)
	{
	  return TRUE;
	}
    }

  return FALSE;
}
