/*
 * # Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


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

#include <gst/gl/gstglfuncs.h>
#include <gst/video/gstvideosink.h>

#include "gstglbox.h"

#define GST_CAT_DEFAULT gst_gl_box_debug
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);

enum
{
  PROP_0,
  PROP_X,
  PROP_Y,
  PROP_WIDTH,
  PROP_HEIGHT,
};

#define DEBUG_INIT \
  GST_DEBUG_CATEGORY_INIT (gst_gl_box_debug, "glbox", 0, "glbox element");
#define gst_gl_box_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstGLBox, gst_gl_box,
    GST_TYPE_GL_FILTER, DEBUG_INIT);

static void gst_gl_box_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_gl_box_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

static gboolean gst_gl_box_gl_start (GstGLBaseFilter * base_filter);
static void gst_gl_box_gl_stop (GstGLBaseFilter * base_filter);
static gboolean gst_gl_box_gl_set_caps (GstGLBaseFilter * bt,
    GstCaps * incaps, GstCaps * outcaps);

static gboolean gst_gl_box_filter_texture (GstGLFilter * filter,
    GstGLMemory * in_tex, GstGLMemory * out_tex);

static void
gst_gl_box_class_init (GstGLBoxClass * klass)
{
  gst_gl_filter_add_rgba_pad_templates (GST_GL_FILTER_CLASS (klass));

  ((GObjectClass *) klass)->set_property = gst_gl_box_set_property;
  ((GObjectClass *) klass)->get_property = gst_gl_box_get_property;

  gst_element_class_set_metadata (GST_ELEMENT_CLASS (klass),
      "OpenGL box",
      "Filter/Effect/Video",
      "Colorspace convert and scale with retained aspect ratio",
      "Coral <coral-support@google.com>");

  GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
  GST_GL_BASE_FILTER_CLASS (klass)->gl_start = GST_DEBUG_FUNCPTR (gst_gl_box_gl_start);
  GST_GL_BASE_FILTER_CLASS (klass)->gl_stop = GST_DEBUG_FUNCPTR (gst_gl_box_gl_stop);
  GST_GL_BASE_FILTER_CLASS (klass)->gl_set_caps = gst_gl_box_gl_set_caps;
  GST_GL_BASE_FILTER_CLASS (klass)->supported_gl_api =
      GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2;
  GST_GL_FILTER_CLASS (klass)->filter_texture = gst_gl_box_filter_texture;

  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X,
      g_param_spec_int ("x", "Frame X coordinate", "Frame X coordinate",
          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_Y,
      g_param_spec_int ("y", "Frame Y coordinate", "Frame Y coordinate",
          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH,
      g_param_spec_int ("width", "Frame width", "Frame width",
          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT,
      g_param_spec_int ("height", "Frame height", "Frame height",
          0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}

static void
gst_gl_box_init (GstGLBox * box)
{
  box->shader = NULL;
  memset (&box->viewport, 0, sizeof (GstVideoRectangle));
}

static void
gst_gl_box_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  switch (prop_id) {
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_gl_box_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstGLBox *box = GST_GL_BOX (object);

  switch (prop_id) {
    case PROP_X:
      g_value_set_int (value, box->viewport.x);
      break;
    case PROP_Y:
      g_value_set_int (value, box->viewport.y);
      break;
    case PROP_WIDTH:
      g_value_set_int (value, box->viewport.w);
      break;
    case PROP_HEIGHT:
      g_value_set_int (value, box->viewport.h);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static gboolean
gst_gl_box_gl_start (GstGLBaseFilter * base_filter)
{
  GstGLBox *box = GST_GL_BOX (base_filter);
  GstGLFilter *filter = GST_GL_FILTER (base_filter);

  box->shader = gst_gl_shader_new_default (base_filter->context, NULL);
  if (!box->shader) {
    GST_ERROR_OBJECT (box, "Failed to initialize shader");
    return FALSE;
  }


  filter->draw_attr_position_loc =
      gst_gl_shader_get_attribute_location (box->shader, "a_position");
  filter->draw_attr_texture_loc =
      gst_gl_shader_get_attribute_location (box->shader, "a_texcoord");

  return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_start (base_filter);
}

static void
gst_gl_box_gl_stop (GstGLBaseFilter * base_filter)
{
  GstGLBox *box = GST_GL_BOX (base_filter);

  if (box->shader) {
    gst_object_unref (box->shader);
    box->shader = NULL;
  }

  GST_GL_BASE_FILTER_CLASS (parent_class)->gl_stop (base_filter);
}

static gboolean
gst_gl_box_gl_set_caps (GstGLBaseFilter * bt, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstGLBox *box = GST_GL_BOX (bt);
  GstGLFilter *filter = GST_GL_FILTER (bt);
  GstVideoRectangle src, dst, viewport;

  src.x = 0;
  src.y = 0;
  src.w = GST_VIDEO_INFO_WIDTH (&filter->in_info);
  src.h = GST_VIDEO_INFO_HEIGHT (&filter->in_info);

  dst.x = 0;
  dst.y = 0;
  dst.w = GST_VIDEO_INFO_WIDTH (&filter->out_info);
  dst.h = GST_VIDEO_INFO_HEIGHT (&filter->out_info);

  gst_video_sink_center_rect (src, dst, &viewport, TRUE);

  if (memcmp (&viewport, &box->viewport, sizeof (GstVideoRectangle))) {
    GST_INFO_OBJECT (filter, "Scaling %dx%d -> %dx%d @ (%d, %d)", src.w, src.h,
        viewport.w, viewport.h, viewport.x, viewport.y);
    box->viewport = viewport;
  }

  return GST_GL_BASE_FILTER_CLASS (parent_class)->gl_set_caps (
      GST_GL_BASE_FILTER (filter), incaps, outcaps);
}

static gboolean
gst_gl_box_draw (GstGLFilter * filter, GstGLMemory * in_tex,
    gpointer user_data)
{
  GstGLBox *box = GST_GL_BOX (user_data);
  const GstGLFuncs *gl = GST_GL_BASE_FILTER (filter)->context->gl_vtable;

  g_return_val_if_fail (box->shader, FALSE);

  gl->ClearColor (0.0, 0.0, 0.0, 1.0);
  gl->Clear (GL_COLOR_BUFFER_BIT);

  gl->Viewport (box->viewport.x, box->viewport.y, box->viewport.w,
      box->viewport.h);

  gst_gl_shader_use (box->shader);
  gst_gl_shader_set_uniform_1i (box->shader, "tex", 0);
  gl->ActiveTexture (GL_TEXTURE0);
  gl->BindTexture (GL_TEXTURE_2D, gst_gl_memory_get_texture_id (in_tex));

  gst_gl_filter_draw_fullscreen_quad (filter);

  return TRUE;
}

static gboolean
gst_gl_box_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
    GstGLMemory * out_tex)
{
  GstGLBox *box = GST_GL_BOX (filter);

  if (gst_gl_context_get_gl_api (GST_GL_BASE_FILTER (filter)->context)) {
    gst_gl_filter_render_to_target (filter, in_tex, out_tex, gst_gl_box_draw,
        filter);
  }

  return TRUE;
}
