/* PIKA - Photo and Image Kooker Application
 * a rebranding of The GNU Image Manipulation Program (created with heckimp)
 * A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
 *
 * Original copyright, applying to most contents (license remains unchanged): 
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 *
 * pikadnd-xds.c
 * Copyright (C) 2005  Sven Neumann <sven@gimp.org>
 *
 * Saving Files via Drag-and-Drop:
 * The Direct Save Protocol for the X Window System
 *
 *   http://www.newplanetsoftware.com/xds/
 *   http://rox.sourceforge.net/xds.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "config.h"

#include <string.h>

#include <gegl.h>
#include <gtk/gtk.h>

#include "libpikabase/pikabase.h"
#include "libpikawidgets/pikawidgets.h"

#include "widgets-types.h"

#include "core/pika.h"
#include "core/pika-utils.h"
#include "core/pikaimage.h"

#include "plug-in/pikapluginmanager-file.h"

#include "file/file-save.h"

#include "pikadnd-xds.h"
#include "pikafiledialog.h"
#include "pikamessagebox.h"
#include "pikamessagedialog.h"

#include "pika-log.h"
#include "pika-intl.h"


#define MAX_URI_LEN 4096


/*  local function prototypes  */

static gboolean   pika_file_overwrite_dialog (GtkWidget *parent,
                                              GFile     *file);


/*  public functions  */

void
pika_dnd_xds_source_set (GdkDragContext *context,
                         PikaImage      *image)
{
  GdkAtom  property;

  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
  g_return_if_fail (image == NULL || PIKA_IS_IMAGE (image));

  PIKA_LOG (DND, NULL);

  property = gdk_atom_intern_static_string ("XdndDirectSave0");

  if (image)
    {
      GdkAtom  type = gdk_atom_intern_static_string ("text/plain");
      GFile   *untitled;
      GFile   *file;
      gchar   *basename;

      basename = g_strconcat (_("Untitled"), ".xcf", NULL);
      untitled = g_file_new_for_path (basename);
      g_free (basename);

      file = pika_image_get_any_file (image);

      if (file)
        {
          GFile *xcf_file = pika_file_with_new_extension (file, untitled);
          basename = g_file_get_basename (xcf_file);
          g_object_unref (xcf_file);
        }
      else
        {
          basename = g_file_get_path (untitled);
        }

      g_object_unref (untitled);

      gdk_property_change (gdk_drag_context_get_source_window (context),
                           property, type, 8, GDK_PROP_MODE_REPLACE,
                           (const guchar *) basename,
                           basename ? strlen (basename) : 0);

      g_free (basename);
    }
  else
    {
      gdk_property_delete (gdk_drag_context_get_source_window (context),
                           property);
    }
}

void
pika_dnd_xds_save_image (GdkDragContext   *context,
                         PikaImage        *image,
                         GtkSelectionData *selection)
{
  PikaPlugInProcedure *proc;
  GdkAtom              property;
  GdkAtom              type;
  gint                 length;
  guchar              *data;
  gchar               *uri;
  GFile               *file;
  gboolean             export = FALSE;
  GError              *error  = NULL;

  g_return_if_fail (GDK_IS_DRAG_CONTEXT (context));
  g_return_if_fail (PIKA_IS_IMAGE (image));

  PIKA_LOG (DND, NULL);

  property = gdk_atom_intern_static_string ("XdndDirectSave0");
  type     = gdk_atom_intern_static_string ("text/plain");

  if (! gdk_property_get (gdk_drag_context_get_source_window (context),
                          property, type,
                          0, MAX_URI_LEN, FALSE,
                          NULL, NULL, &length, &data))
    return;


  uri = g_strndup ((const gchar *) data, length);
  g_free (data);

  file = g_file_new_for_uri (uri);

  proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
                                                   PIKA_FILE_PROCEDURE_GROUP_SAVE,
                                                   file, NULL);
  if (! proc)
    {
      proc = pika_plug_in_manager_file_procedure_find (image->pika->plug_in_manager,
                                                       PIKA_FILE_PROCEDURE_GROUP_EXPORT,
                                                       file, NULL);
      export = TRUE;
    }

  if (proc)
    {
      if (! g_file_query_exists (file, NULL) ||
          pika_file_overwrite_dialog (NULL, file))
        {
          if (file_save (image->pika,
                         image, NULL,
                         file, proc, PIKA_RUN_INTERACTIVE,
                         ! export, FALSE, export,
                         &error) == PIKA_PDB_SUCCESS)
            {
              gtk_selection_data_set (selection,
                                      gtk_selection_data_get_target (selection),
                                      8, (const guchar *) "S", 1);
            }
          else
            {
              gtk_selection_data_set (selection,
                                      gtk_selection_data_get_target (selection),
                                      8, (const guchar *) "E", 1);

              if (error)
                {
                  pika_message (image->pika, NULL, PIKA_MESSAGE_ERROR,
                                _("Saving '%s' failed:\n\n%s"),
                                pika_file_get_utf8_name (file),
                                error->message);
                  g_clear_error (&error);
                }
            }
        }
    }
  else
    {
      gtk_selection_data_set (selection,
                              gtk_selection_data_get_target (selection),
                              8, (const guchar *) "E", 1);

      pika_message_literal (image->pika, NULL, PIKA_MESSAGE_ERROR,
                            _("The given filename does not have any known "
                              "file extension."));
    }

  g_object_unref (file);
  g_free (uri);
}


/*  private functions  */

static gboolean
pika_file_overwrite_dialog (GtkWidget *parent,
                            GFile     *file)
{
  GtkWidget *dialog;
  gboolean   overwrite = FALSE;

  dialog = pika_message_dialog_new (_("File Exists"),
                                    PIKA_ICON_DIALOG_WARNING,
                                    parent, GTK_DIALOG_DESTROY_WITH_PARENT,
                                    pika_standard_help_func, NULL,

                                    _("_Cancel"),  GTK_RESPONSE_CANCEL,
                                    _("_Replace"), GTK_RESPONSE_OK,

                                    NULL);

  pika_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
                                           GTK_RESPONSE_OK,
                                           GTK_RESPONSE_CANCEL,
                                           -1);

  pika_message_box_set_primary_text (PIKA_MESSAGE_DIALOG (dialog)->box,
                                     _("A file named '%s' already exists."),
                                     pika_file_get_utf8_name (file));

  pika_message_box_set_text (PIKA_MESSAGE_DIALOG (dialog)->box,
                             _("Do you want to replace it with the image "
                               "you are saving?"));

  if (GTK_IS_DIALOG (parent))
    gtk_dialog_set_response_sensitive (GTK_DIALOG (parent),
                                       GTK_RESPONSE_CANCEL, FALSE);

  g_object_ref (dialog);

  overwrite = (pika_dialog_run (PIKA_DIALOG (dialog)) == GTK_RESPONSE_OK);

  gtk_widget_destroy (dialog);
  g_object_unref (dialog);

  if (GTK_IS_DIALOG (parent))
    gtk_dialog_set_response_sensitive (GTK_DIALOG (parent),
                                       GTK_RESPONSE_CANCEL, TRUE);

  return overwrite;
}
