/*
 * Copyright 2015 Red Hat, Inc.
 *
 * This library 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 2 of the licence, or (at your option) any later version.
 *
 * This library 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 library; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Matthias Clasen <mclasen@redhat.com>
 */

#include "config.h"

#include <gio/gio.h>
#include <gi18n.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "gio-tool.h"

static const GOptionEntry entries[] = {
  { NULL }
};

static GAppInfo *
get_app_info_for_id (const char *id)
{
  GList *list, *l;
  GAppInfo *ret_info;

  list = g_app_info_get_all ();
  ret_info = NULL;
  for (l = list; l != NULL; l = l->next)
    {
      GAppInfo *info;

      info = l->data;
      if (ret_info == NULL && g_strcmp0 (g_app_info_get_id (info), id) == 0)
        ret_info = info;
      else
        g_object_unref (info);
    }
  g_list_free (list);

  return ret_info;
}

int
handle_mime (int argc, char *argv[], gboolean do_help)
{
  GOptionContext *context;
  GError *error = NULL;
  gchar *param;
  const gchar *mimetype;
  const char *handler;

  g_set_prgname ("gio mime");

  /* Translators: commandline placeholder */
  param = g_strdup_printf ("%s [%s]", _("MIMETYPE"), _("HANDLER"));
  context = g_option_context_new (param);
  g_free (param);
  g_option_context_set_help_enabled (context, FALSE);
  g_option_context_set_summary (context,
      _("Get or set the handler for a mimetype."));
  g_option_context_set_description (context,
      _("If no handler is given, lists registered and recommended applications\n"
        "for the mimetype. If a handler is given, it is set as the default\n"
        "handler for the mimetype."));
  g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);

  if (do_help)
    {
      show_help (context, NULL);
      return 0;
    }

  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      show_help (context, error->message);
      g_error_free (error);
      return 1;
    }

  if (argc != 2 && argc != 3)
    {
      show_help (context, _("Must specify a single mimetype, and maybe a handler"));
      return 1;
    }

  g_option_context_free (context);

  if (argc == 2)
    {
      GAppInfo *info;

      mimetype = argv[1];

      info = g_app_info_get_default_for_type (mimetype, FALSE);
      if (!info)
        {
          g_print (_("No default applications for “%s”\n"), mimetype);
        }
      else
        {
          GList *list, *l;

          g_print (_("Default application for “%s”: %s\n"), mimetype, g_app_info_get_id (info));
          g_object_unref (info);

          list = g_app_info_get_all_for_type (mimetype);
          if (list != NULL)
            g_print (_("Registered applications:\n"));
          else
            g_print (_("No registered applications\n"));
          for (l = list; l != NULL; l = l->next)
            {
              info = l->data;
              g_print ("\t%s\n", g_app_info_get_id (info));
              g_object_unref (info);
            }
          g_list_free (list);

          list = g_app_info_get_recommended_for_type (mimetype);
          if (list != NULL)
            g_print (_("Recommended applications:\n"));
          else
            g_print (_("No recommended applications\n"));
          for (l = list; l != NULL; l = l->next)
            {
              info = l->data;
              g_print ("\t%s\n", g_app_info_get_id (info));
              g_object_unref (info);
            }
          g_list_free (list);
        }
    }
  else
    {
      GAppInfo *info;

      mimetype = argv[1];
      handler = argv[2];

      info = get_app_info_for_id (handler);
      if (info == NULL)
        {
          g_printerr (_("Failed to load info for handler “%s”\n"), handler);
          return 1;
        }

      if (g_app_info_set_as_default_for_type (info, mimetype, &error) == FALSE)
        {
          g_printerr (_("Failed to set “%s” as the default handler for “%s”: %s\n"),
                      handler, mimetype, error->message);
          g_error_free (error);
          g_object_unref (info);
          return 1;
        }
      g_print ("Set %s as the default for %s\n", g_app_info_get_id (info), mimetype);
      g_object_unref (info);
    }

  return 0;
}
