/* poppler-movie.cc: glib interface to Movie
 *
 * Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 * Copyright (C) 2008 Hugo Mercier <hmercier31[@]gmail.com>
 * Copyright (C) 2017 Francesco Poli <invernomuto@paranoici.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 "poppler-movie.h"
#include "poppler-private.h"

/**
 * SECTION: poppler-movie
 * @short_description: Movies
 * @title: PopplerMovie
 */

typedef struct _PopplerMovieClass PopplerMovieClass;

struct _PopplerMovie
{
  GObject   parent_instance;

  gchar   *filename;
  gboolean need_poster;
  gboolean show_controls;
  PopplerMoviePlayMode mode;
};

struct _PopplerMovieClass
{
  GObjectClass parent_class;
};

G_DEFINE_TYPE (PopplerMovie, poppler_movie, G_TYPE_OBJECT)

static void
poppler_movie_finalize (GObject *object)
{
  PopplerMovie* movie = POPPLER_MOVIE(object);

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

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

static void
poppler_movie_class_init (PopplerMovieClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = poppler_movie_finalize;
}

static void
poppler_movie_init (PopplerMovie *movie)
{
}

PopplerMovie *
_poppler_movie_new (const Movie *poppler_movie)
{
  PopplerMovie *movie;

  g_assert (poppler_movie != nullptr);

  movie = POPPLER_MOVIE (g_object_new (POPPLER_TYPE_MOVIE, nullptr));

  movie->filename = g_strdup (poppler_movie->getFileName()->getCString());
  if (poppler_movie->getShowPoster()) {
    Object tmp = poppler_movie->getPoster();
    movie->need_poster = (!tmp.isRef() && !tmp.isStream());
  }

  movie->show_controls = poppler_movie->getActivationParameters()->showControls;

  switch (poppler_movie->getActivationParameters()->repeatMode) {
  case MovieActivationParameters::repeatModeOnce:
    movie->mode = POPPLER_MOVIE_PLAY_MODE_ONCE;
    break;
  case MovieActivationParameters::repeatModeOpen:
    movie->mode = POPPLER_MOVIE_PLAY_MODE_OPEN;
    break;
  case MovieActivationParameters::repeatModeRepeat:
    movie->mode = POPPLER_MOVIE_PLAY_MODE_REPEAT;
    break;
  case MovieActivationParameters::repeatModePalindrome:
    movie->mode = POPPLER_MOVIE_PLAY_MODE_PALINDROME;
    break;
  }

  return movie;
}

/**
* poppler_movie_get_filename:
* @poppler_movie: a #PopplerMovie
*
* Returns the local filename identifying a self-describing movie file
*
* Return value: a local filename, return value is owned by #PopplerMovie and
*               should not be freed
*
* Since: 0.14
*/
const gchar *
poppler_movie_get_filename (PopplerMovie *poppler_movie)
{
  g_return_val_if_fail (POPPLER_IS_MOVIE (poppler_movie), NULL);

  return poppler_movie->filename;
}

/**
 * poppler_movie_need_poster:
 * @poppler_movie: a #PopplerMovie
 *
 * Returns whether a poster image representing the Movie
 * shall be displayed. The poster image must be retrieved
 * from the movie file.
 *
 * Return value: %TRUE if move needs a poster image, %FALSE otherwise
 *
 * Since: 0.14
 */
gboolean
poppler_movie_need_poster (PopplerMovie *poppler_movie)
{
  g_return_val_if_fail (POPPLER_IS_MOVIE (poppler_movie), FALSE);

  return poppler_movie->need_poster;
}

/**
 * poppler_movie_show_controls:
 * @poppler_movie: a #PopplerMovie
 *
 * Returns whether to display a movie controller bar while playing the movie
 *
 * Return value: %TRUE if controller bar should be displayed, %FALSE otherwise
 *
 * Since: 0.14
 */
gboolean
poppler_movie_show_controls (PopplerMovie *poppler_movie)
{
  g_return_val_if_fail (POPPLER_IS_MOVIE (poppler_movie), FALSE);

  return poppler_movie->show_controls;
}

/**
 * poppler_movie_get_play_mode:
 * @poppler_movie: a #PopplerMovie
 *
 * Returns the play mode of @poppler_movie.
 *
 * Return value: a #PopplerMoviePlayMode.
 *
 * Since: 0.54
 */
PopplerMoviePlayMode
poppler_movie_get_play_mode (PopplerMovie *poppler_movie)
{
  g_return_val_if_fail (POPPLER_IS_MOVIE (poppler_movie), POPPLER_MOVIE_PLAY_MODE_ONCE);

  return poppler_movie->mode;
}
