/*
 * GStreamer
 * Copyright (C) 2006 James Livingston <doclivingston@gmail.com>
 * Copyright (C) 2008 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

/**
 * SECTION:element-katetag
 * @title: katetag
 * @see_also: #oggdemux, #oggmux, #kateparse, #GstTagSetter
 * @short_description: retags kate streams
 *
 * The katetag element can change the tag contained within a raw
 * kate stream. Specifically, it modifies the comments header packet
 * of the kate stream, as well as the language and category of the
 * kate stream.
 *
 * The element will also process the stream as the #kateparse element does
 * so it can be used when remuxing an Ogg Kate stream, without additional
 * elements.
 *
 * Applications can set the tags to write using the #GstTagSetter interface.
 * Tags contained within the kate stream will be picked up
 * automatically (and merged according to the merge mode set via the tag
 * setter interface).
 *
 * ## Example pipelines
 *
 * This element is only useful with gst-launch-1.0 for modifying the language
 * and/or category (which are properties of the stream located in the kate
 * beginning of stream header), because it does not support setting the tags
 * on a #GstTagSetter interface. Conceptually, the element will usually be
 * used like:
 * |[
 * gst-launch-1.0 -v filesrc location=foo.ogg ! oggdemux ! katetag ! oggmux ! filesink location=bar.ogg
 * ]|
 *
 * This pipeline will set the language and category of the stream to the
 * given values:
 * |[
 * gst-launch-1.0 -v filesrc location=foo.ogg ! oggdemux ! katetag language=pt_BR category=subtitles ! oggmux ! filesink location=bar.ogg
 * ]|
 *
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <string.h>
#include <glib.h>
#include <gst/tag/tag.h>
#include <gst/gsttagsetter.h>

#include <kate/kate.h>

#include "gstkatetag.h"


GST_DEBUG_CATEGORY_EXTERN (gst_katetag_debug);
#define GST_CAT_DEFAULT gst_katetag_debug

enum
{
  ARG_0,
  ARG_LANGUAGE,
  ARG_CATEGORY,
  ARG_ORIGINAL_CANVAS_WIDTH,
  ARG_ORIGINAL_CANVAS_HEIGHT,
};

static GstFlowReturn gst_kate_tag_parse_packet (GstKateParse * parse,
    GstBuffer * buffer);
static void gst_kate_tag_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_kate_tag_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_kate_tag_dispose (GObject * object);

#define gst_kate_tag_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstKateTag, gst_kate_tag, GST_TYPE_KATE_PARSE,
    G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));

static void
gst_kate_tag_class_init (GstKateTagClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
  GstKateParseClass *gstkateparse_class;

  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
  gstkateparse_class = GST_KATE_PARSE_CLASS (klass);

  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_tag_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_tag_get_property);
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_tag_dispose);

  g_object_class_install_property (gobject_class, ARG_LANGUAGE,
      g_param_spec_string ("language", "Language",
          "Set the language of the stream", "",
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, ARG_CATEGORY,
      g_param_spec_string ("category", "Category",
          "Set the category of the stream", "",
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_WIDTH,
      g_param_spec_int ("original-canvas-width", "Original canvas width",
          "Set the width of the canvas this stream was authored for (0 is unspecified)",
          0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_HEIGHT,
      g_param_spec_int ("original-canvas-height", "Original canvas height",
          "Set the height of the canvas this stream was authored for (0 is unspecified)",
          0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  gst_element_class_set_static_metadata (gstelement_class, "Kate stream tagger",
      "Formatter/Metadata",
      "Retags kate streams", "Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");

  gstkateparse_class->parse_packet =
      GST_DEBUG_FUNCPTR (gst_kate_tag_parse_packet);
}

static void
gst_kate_tag_init (GstKateTag * kt)
{
  kt->language = NULL;
  kt->category = NULL;
  kt->original_canvas_width = -1;
  kt->original_canvas_height = -1;
}

static void
gst_kate_tag_dispose (GObject * object)
{
  GstKateTag *kt = GST_KATE_TAG (object);

  GST_LOG_OBJECT (kt, "disposing");

  if (kt->language) {
    g_free (kt->language);
    kt->language = NULL;
  }
  if (kt->category) {
    g_free (kt->category);
    kt->category = NULL;
  }

  GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}

static void
gst_kate_tag_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstKateTag *kt = GST_KATE_TAG (object);
  const char *str;

  switch (prop_id) {
    case ARG_LANGUAGE:
      if (kt->language) {
        g_free (kt->language);
        kt->language = NULL;
      }
      str = g_value_get_string (value);
      if (str)
        kt->language = g_strdup (str);
      break;
    case ARG_CATEGORY:
      if (kt->category) {
        g_free (kt->category);
        kt->category = NULL;
      }
      str = g_value_get_string (value);
      if (str)
        kt->category = g_strdup (str);
      break;
    case ARG_ORIGINAL_CANVAS_WIDTH:
      kt->original_canvas_width = g_value_get_int (value);
      break;
    case ARG_ORIGINAL_CANVAS_HEIGHT:
      kt->original_canvas_height = g_value_get_int (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_kate_tag_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstKateTag *kt = GST_KATE_TAG (object);

  switch (prop_id) {
    case ARG_LANGUAGE:
      g_value_set_string (value, kt->language ? kt->language : "");
      break;
    case ARG_CATEGORY:
      g_value_set_string (value, kt->category ? kt->category : "");
      break;
    case ARG_ORIGINAL_CANVAS_WIDTH:
      g_value_set_int (value, kt->original_canvas_width);
      break;
    case ARG_ORIGINAL_CANVAS_HEIGHT:
      g_value_set_int (value, kt->original_canvas_height);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static guint16
encode_canvas_size (size_t size)
{
  size_t base = size;
  size_t shift = 0;
  int value;

  while (base & ~((1 << 12) - 1)) {
    /* we have a high bit we can't fit, increase shift if we wouldn't lose low bits */
    if ((size >> shift) & 1)
      return 0;
    ++shift;
    base >>= 1;
  }
  if (G_UNLIKELY (shift >= 16))
    return 0;

  /* the size can be represented in our encoding */
  value = (base << 4) | shift;

  return (guint16) value;
}

static GstFlowReturn
gst_kate_tag_parse_packet (GstKateParse * parse, GstBuffer * buffer)
{
  GstTagList *old_tags, *new_tags;
  const GstTagList *user_tags;
  GstKateTag *kt;
  gchar *encoder = NULL;
  GstBuffer *new_buf;
  GstMapInfo info;

  kt = GST_KATE_TAG (parse);

  if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) {
    GST_ERROR_OBJECT (parse, "Failed to map buffer");
    return GST_FLOW_ERROR;
  }

  /* rewrite the language and category */
  if (info.size >= 64 && info.data[0] == 0x80) {
    GstBuffer *new_buffer;

    gst_buffer_unmap (buffer, &info);
    new_buffer = gst_buffer_copy (buffer);
    gst_buffer_unref (buffer);
    buffer = new_buffer;

    if (!gst_buffer_map (buffer, &info, GST_MAP_READWRITE)) {
      GST_ERROR_OBJECT (parse, "Failed to map copied buffer READWRITE");
      return GST_FLOW_ERROR;
    }
    /* language is at offset 32, 16 bytes, zero terminated */
    if (kt->language) {
      strncpy ((char *) info.data + 32, kt->language, 15);
      info.data[47] = 0;
    }
    /* category is at offset 48, 16 bytes, zero terminated */
    if (kt->category) {
      strncpy ((char *) info.data + 48, kt->category, 15);
      info.data[63] = 0;
    }
    if (kt->original_canvas_width >= 0) {
      guint16 v = encode_canvas_size (kt->original_canvas_width);
      info.data[16] = v & 0xff;
      info.data[17] = (v >> 8) & 0xff;
    }
    if (kt->original_canvas_height >= 0) {
      guint16 v = encode_canvas_size (kt->original_canvas_height);
      info.data[18] = v & 0xff;
      info.data[19] = (v >> 8) & 0xff;
    }
  }

  /*  rewrite the comments packet */
  if (info.size >= 9 && info.data[0] == 0x81) {
    old_tags =
        gst_tag_list_from_vorbiscomment (info.data, info.size,
        (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
    user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (kt));
    gst_buffer_unmap (buffer, &info);

    /* build new tag list */
    new_tags = gst_tag_list_merge (user_tags, old_tags,
        gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (kt)));
    gst_tag_list_unref (old_tags);

    new_buf =
        gst_tag_list_to_vorbiscomment_buffer (new_tags,
        (const guint8 *) "\201kate\0\0\0\0", 9, encoder);
    gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);

    gst_tag_list_unref (new_tags);
    g_free (encoder);
    gst_buffer_unref (buffer);

    /* the buffer will have the framing bit used by Vorbis, but we don't use it */
    gst_buffer_resize (new_buf, 0, gst_buffer_get_size (new_buf) - 1);

    buffer = new_buf;
  } else {
    gst_buffer_unmap (buffer, &info);
  }

  return GST_KATE_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);
}
