// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/platform/linux/public/flutter_linux/fl_texture_registrar.h"

#include <gmodule.h>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_pixel_buffer_texture_private.h"
#include "flutter/shell/platform/linux/fl_texture_gl_private.h"
#include "flutter/shell/platform/linux/fl_texture_private.h"
#include "flutter/shell/platform/linux/fl_texture_registrar_private.h"

G_DECLARE_FINAL_TYPE(FlTextureRegistrarImpl,
                     fl_texture_registrar_impl,
                     FL,
                     TEXTURE_REGISTRAR_IMPL,
                     GObject)

struct _FlTextureRegistrarImpl {
  GObject parent_instance;

  // Weak reference to the engine this texture registrar is created for.
  FlEngine* engine;

  // ID to assign to the next new texture.
  int64_t next_id;

  // Internal record for registered textures.
  //
  // It is a map from Flutter texture ID to #FlTexture instance created by
  // plugins.  The keys are directly stored int64s. The values are stored
  // pointer to #FlTexture.  This table is freed by the responder.
  GHashTable* textures;

  // The mutex guard to make `textures` thread-safe.
  GMutex textures_mutex;
};

static void fl_texture_registrar_impl_iface_init(
    FlTextureRegistrarInterface* iface);

G_DEFINE_INTERFACE(FlTextureRegistrar, fl_texture_registrar, G_TYPE_OBJECT)

G_DEFINE_TYPE_WITH_CODE(
    FlTextureRegistrarImpl,
    fl_texture_registrar_impl,
    G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE(fl_texture_registrar_get_type(),
                          fl_texture_registrar_impl_iface_init))

static void fl_texture_registrar_default_init(
    FlTextureRegistrarInterface* iface) {}

static void engine_weak_notify_cb(gpointer user_data,
                                  GObject* where_the_object_was) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(user_data);
  self->engine = nullptr;

  // Unregister any textures.
  g_mutex_lock(&self->textures_mutex);
  g_autoptr(GHashTable) textures = self->textures;
  self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
                                         g_object_unref);
  g_hash_table_remove_all(textures);
  g_mutex_unlock(&self->textures_mutex);
}

static void fl_texture_registrar_impl_dispose(GObject* object) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(object);

  g_mutex_lock(&self->textures_mutex);
  g_clear_pointer(&self->textures, g_hash_table_unref);
  g_mutex_unlock(&self->textures_mutex);

  if (self->engine != nullptr) {
    g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self);
    self->engine = nullptr;
  }
  g_mutex_clear(&self->textures_mutex);

  G_OBJECT_CLASS(fl_texture_registrar_impl_parent_class)->dispose(object);
}

static void fl_texture_registrar_impl_class_init(
    FlTextureRegistrarImplClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_texture_registrar_impl_dispose;
}

static gboolean register_texture(FlTextureRegistrar* registrar,
                                 FlTexture* texture) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);

  if (FL_IS_TEXTURE_GL(texture) || FL_IS_PIXEL_BUFFER_TEXTURE(texture)) {
    if (self->engine == nullptr) {
      return FALSE;
    }

    // We ideally would use numeric IDs, but for backwards compatibility with
    // existing code use the address of the texture. Once all code uses
    // fl_texture_get_id we can re-enable this method. See
    // https://github.com/flutter/flutter/issues/124009 int64_t id =
    // self->next_id++;
    int64_t id = reinterpret_cast<int64_t>(texture);
    if (fl_engine_register_external_texture(self->engine, id)) {
      fl_texture_set_id(texture, id);
      g_mutex_lock(&self->textures_mutex);
      g_hash_table_insert(self->textures, GINT_TO_POINTER(id),
                          g_object_ref(texture));
      g_mutex_unlock(&self->textures_mutex);
      return TRUE;
    } else {
      return FALSE;
    }
  } else {
    // We currently only support #FlTextureGL and #FlPixelBufferTexture.
    return FALSE;
  }
}

static FlTexture* lookup_texture(FlTextureRegistrar* registrar,
                                 int64_t texture_id) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);
  g_mutex_lock(&self->textures_mutex);
  FlTexture* texture = reinterpret_cast<FlTexture*>(
      g_hash_table_lookup(self->textures, GINT_TO_POINTER(texture_id)));
  g_mutex_unlock(&self->textures_mutex);
  return texture;
}

static gboolean mark_texture_frame_available(FlTextureRegistrar* registrar,
                                             FlTexture* texture) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);

  if (self->engine == nullptr) {
    return FALSE;
  }

  return fl_engine_mark_texture_frame_available(self->engine,
                                                fl_texture_get_id(texture));
}

static gboolean unregister_texture(FlTextureRegistrar* registrar,
                                   FlTexture* texture) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(registrar);

  if (self->engine == nullptr) {
    return FALSE;
  }

  gboolean result = fl_engine_unregister_external_texture(
      self->engine, fl_texture_get_id(texture));

  g_mutex_lock(&self->textures_mutex);
  if (!g_hash_table_remove(self->textures,
                           GINT_TO_POINTER(fl_texture_get_id(texture)))) {
    g_warning("Unregistering a non-existent texture %p", texture);
  }
  g_mutex_unlock(&self->textures_mutex);

  return result;
}

static void fl_texture_registrar_impl_iface_init(
    FlTextureRegistrarInterface* iface) {
  iface->register_texture = register_texture;
  iface->lookup_texture = lookup_texture;
  iface->mark_texture_frame_available = mark_texture_frame_available;
  iface->unregister_texture = unregister_texture;
}

static void fl_texture_registrar_impl_init(FlTextureRegistrarImpl* self) {
  self->next_id = 1;
  self->textures = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
                                         g_object_unref);
  // Initialize the mutex for textures.
  g_mutex_init(&self->textures_mutex);
}

G_MODULE_EXPORT gboolean fl_texture_registrar_register_texture(
    FlTextureRegistrar* self,
    FlTexture* texture) {
  g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);
  g_return_val_if_fail(FL_IS_TEXTURE(texture), FALSE);

  return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->register_texture(self, texture);
}

FlTexture* fl_texture_registrar_lookup_texture(FlTextureRegistrar* self,
                                               int64_t texture_id) {
  g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), NULL);

  return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->lookup_texture(self, texture_id);
}

G_MODULE_EXPORT gboolean fl_texture_registrar_mark_texture_frame_available(
    FlTextureRegistrar* self,
    FlTexture* texture) {
  g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);

  return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->mark_texture_frame_available(
      self, texture);
}

G_MODULE_EXPORT gboolean fl_texture_registrar_unregister_texture(
    FlTextureRegistrar* self,
    FlTexture* texture) {
  g_return_val_if_fail(FL_IS_TEXTURE_REGISTRAR(self), FALSE);

  return FL_TEXTURE_REGISTRAR_GET_IFACE(self)->unregister_texture(self,
                                                                  texture);
}

FlTextureRegistrar* fl_texture_registrar_new(FlEngine* engine) {
  FlTextureRegistrarImpl* self = FL_TEXTURE_REGISTRAR_IMPL(
      g_object_new(fl_texture_registrar_impl_get_type(), nullptr));

  // Added to stop compiler complaining about an unused function.
  FL_IS_TEXTURE_REGISTRAR_IMPL(self);

  self->engine = engine;
  g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, self);

  return FL_TEXTURE_REGISTRAR(self);
}
