/* poppler-media.cc: glib interface to MediaRendition
 *
 * Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 *
 * 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 2, 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include <errno.h>

#include <goo/gfile.h>

#include "poppler-media.h"
#include "poppler-private.h"

/**
 * SECTION: poppler-media
 * @short_description: Media
 * @title: PopplerMedia
 */

typedef struct _PopplerMediaClass PopplerMediaClass;

struct _PopplerMedia
{
  GObject   parent_instance;

  gchar  *filename;

  gchar  *mime_type;
  Object stream;
};

struct _PopplerMediaClass
{
  GObjectClass parent_class;
};

G_DEFINE_TYPE (PopplerMedia, poppler_media, G_TYPE_OBJECT)

static void
poppler_media_finalize (GObject *object)
{
  PopplerMedia *media = POPPLER_MEDIA(object);

  if (media->filename) {
    g_free (media->filename);
    media->filename = nullptr;
  }

  if (media->mime_type) {
    g_free (media->mime_type);
    media->mime_type = nullptr;
  }

  media->stream = Object();

  G_OBJECT_CLASS (poppler_media_parent_class)->finalize (object);
}

static void
poppler_media_class_init (PopplerMediaClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = poppler_media_finalize;
}

static void
poppler_media_init (PopplerMedia *media)
{
}

PopplerMedia *
_poppler_media_new (const MediaRendition *poppler_media)
{
  PopplerMedia *media;

  g_assert (poppler_media != nullptr);

  media = POPPLER_MEDIA (g_object_new (POPPLER_TYPE_MEDIA, nullptr));

  if (poppler_media->getIsEmbedded()) {
    const GooString* mime_type;

    media->stream = poppler_media->getEmbbededStreamObject()->copy();
    mime_type = poppler_media->getContentType();
    if (mime_type)
      media->mime_type = g_strdup (mime_type->c_str());
  } else {
    media->filename = g_strdup (poppler_media->getFileName()->c_str());
  }

  return media;
}

/**
* poppler_media_get_filename:
* @poppler_media: a #PopplerMedia
*
* Returns the media clip filename, in case of non-embedded media. filename might be
* a local relative or absolute path or a URI
*
* Return value: a filename, return value is owned by #PopplerMedia and should not be freed
*
* Since: 0.14
*/
const gchar *
poppler_media_get_filename (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), NULL);
  g_return_val_if_fail (!poppler_media->stream.isStream(), NULL);

  return poppler_media->filename;
}

/**
 * poppler_media_is_embedded:
 * @poppler_media: a #PopplerMedia
 *
 * Whether the media clip is embedded in the PDF. If the result is %TRUE, the embedded stream
 * can be saved with poppler_media_save() or poppler_media_save_to_callback() function.
 * If the result is %FALSE, the media clip filename can be retrieved with
 * poppler_media_get_filename() function.
 *
 * Return value: %TRUE if media clip is embedded, %FALSE otherwise
 *
 * Since: 0.14
 */
gboolean
poppler_media_is_embedded (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);

  return poppler_media->stream.isStream();
}

/**
 * poppler_media_get_mime_type:
 * @poppler_media: a #PopplerMedia
 *
 * Returns the media clip mime-type
 *
 * Return value: the mime-type, return value is owned by #PopplerMedia and should not be freed
 *
 * Since: 0.14
 */
const gchar *
poppler_media_get_mime_type (PopplerMedia *poppler_media)
{
  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), NULL);

  return poppler_media->mime_type;
}

static gboolean
save_helper (const gchar  *buf,
	     gsize         count,
	     gpointer      data,
	     GError      **error)
{
  FILE *f = (FILE *) data;
  gsize n;

  n = fwrite (buf, 1, count, f);
  if (n != count)
    {
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Error writing to media file: %s",
		   g_strerror (errno));
      return FALSE;
    }

  return TRUE;
}

/**
 * poppler_media_save:
 * @poppler_media: a #PopplerMedia
 * @filename: name of file to save
 * @error: (allow-none): return location for error, or %NULL.
 *
 * Saves embedded stream of @poppler_media to a file indicated by @filename.
 * If @error is set, %FALSE will be returned.
 * Possible errors include those in the #G_FILE_ERROR domain
 * and whatever the save function generates.
 *
 * Return value: %TRUE, if the file successfully saved
 *
 * Since: 0.14
 */
gboolean
poppler_media_save (PopplerMedia *poppler_media,
		    const char   *filename,
		    GError      **error)
{
  gboolean result;
  FILE *f;

  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);
  g_return_val_if_fail (poppler_media->stream.isStream(), FALSE);

  f = openFile (filename, "wb");

  if (f == nullptr)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Failed to open '%s' for writing: %s",
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  result = poppler_media_save_to_callback (poppler_media, save_helper, f, error);

  if (fclose (f) < 0)
    {
      gchar *display_name = g_filename_display_name (filename);
      g_set_error (error,
		   G_FILE_ERROR,
		   g_file_error_from_errno (errno),
		   "Failed to close '%s', all data may not have been saved: %s",
		   display_name,
		   g_strerror (errno));
      g_free (display_name);
      return FALSE;
    }

  return result;
}

#define BUF_SIZE 1024

/**
 * poppler_media_save_to_callback:
 * @poppler_media: a #PopplerMedia
 * @save_func: (scope call): a function that is called to save each block of data that the save routine generates.
 * @user_data: user data to pass to the save function.
 * @error: (allow-none): return location for error, or %NULL.
 *
 * Saves embedded stream of @poppler_media by feeding the produced data to @save_func. Can be used
 * when you want to store the media clip stream to something other than a file, such as
 * an in-memory buffer or a socket. If @error is set, %FALSE will be
 * returned. Possible errors include those in the #G_FILE_ERROR domain and
 * whatever the save function generates.
 *
 * Return value: %TRUE, if the save successfully completed
 *
 * Since: 0.14
 */
gboolean
poppler_media_save_to_callback (PopplerMedia        *poppler_media,
				PopplerMediaSaveFunc save_func,
				gpointer             user_data,
				GError             **error)
{
  Stream *stream;
  gchar buf[BUF_SIZE];
  int i;
  gboolean eof_reached = FALSE;

  g_return_val_if_fail (POPPLER_IS_MEDIA (poppler_media), FALSE);
  g_return_val_if_fail (poppler_media->stream.isStream(), FALSE);

  stream = poppler_media->stream.getStream();
  stream->reset();

  do
    {
      int data;

      for (i = 0; i < BUF_SIZE; i++)
	{
	  data = stream->getChar ();
	  if (data == EOF)
	    {
	      eof_reached = TRUE;
	      break;
	    }
	  buf[i] = data;
	}

      if (i > 0)
	{
	  if (! (save_func) (buf, i, user_data, error))
	    {
	      stream->close ();
	      return FALSE;
	    }
	}
    }
  while (! eof_reached);

  stream->close ();

  return TRUE;
}
