#ifdef RIVE_WASM_MODULE
// In-module implementations of the abstract render interfaces the bindings
// call through: geometry stays in module memory as RawPath and syncs to the
// host lazily; every native contact is a u32 handle crossing a rive_*_v1
// import. Compiled only into the script module (never the runtime).
#include "rive/factory.hpp"
#include "rive/math/raw_path.hpp"
#include "rive/renderer.hpp"
#include "rive/wasm/module_render.hpp"
#include "rive/wasm/rive_bindings_v1.h"

#include <stdio.h>

using namespace rive;

namespace
{

class ModuleRenderPath : public RenderPath
{
public:
  ModuleRenderPath() = default;
  ModuleRenderPath(RawPath& rawPath, FillRule rule)
      : m_rawPath(rawPath)
      , m_fillRule(rule)
  {}
  ~ModuleRenderPath() override
  {
    if (m_handle != 0)
    {
      rive_path_release(m_handle);
    }
  }

  void rewind() override
  {
    m_rawPath.rewind();
    m_dirty = true;
  }
  void fillRule(FillRule value) override
  {
    m_fillRule = value;
    m_dirty = true;
  }
  void addPath(CommandPath* path, const Mat2D& transform) override
  {
    addRenderPath(path->renderPath(), transform);
  }
  void addRenderPath(const RenderPath* path, const Mat2D& transform) override
  {
    auto modulePath = static_cast<const ModuleRenderPath*>(path);
    m_rawPath.addPath(modulePath->m_rawPath, &transform);
    m_dirty = true;
  }
  void moveTo(float x, float y) override
  {
    m_rawPath.moveTo(x, y);
    m_dirty = true;
  }
  void lineTo(float x, float y) override
  {
    m_rawPath.lineTo(x, y);
    m_dirty = true;
  }
  void cubicTo(float ox, float oy, float ix, float iy, float x, float y)
      override
  {
    m_rawPath.cubicTo(ox, oy, ix, iy, x, y);
    m_dirty = true;
  }
  void close() override
  {
    m_rawPath.close();
    m_dirty = true;
  }
  void addRawPath(const RawPath& path) override
  {
    m_rawPath.addPath(path, nullptr);
    m_dirty = true;
  }

  // Pushes geometry to the host when it changed since the last draw.
  uint32_t sync()
  {
    if (m_handle == 0)
    {
      m_handle = rive_path_new();
      m_dirty = true;
    }
    if (m_dirty)
    {
      rive_path_update(
          m_handle,
          (const uint8_t*)m_rawPath.verbs().data(),
          (uint32_t)m_rawPath.verbs().size(),
          (const float*)m_rawPath.points().data(),
          (uint32_t)m_rawPath.points().size() * 2,
          (uint32_t)m_fillRule);
      m_dirty = false;
    }
    return m_handle;
  }

private:
  RawPath m_rawPath;
  FillRule m_fillRule = FillRule::nonZero;
  uint32_t m_handle = 0;
  bool m_dirty = false;
};

class ModuleRenderPaint : public RenderPaint
{
public:
  ModuleRenderPaint() : m_handle(rive_paint_new()) {}
  ~ModuleRenderPaint() override { rive_paint_release(m_handle); }

  void style(RenderPaintStyle value) override
  {
    rive_paint_style(m_handle, (uint32_t)value);
  }
  void color(ColorInt value) override { rive_paint_color(m_handle, value); }
  void thickness(float value) override
  {
    rive_paint_thickness(m_handle, value);
  }
  void join(StrokeJoin value) override
  {
    rive_paint_join(m_handle, (uint32_t)value);
  }
  void cap(StrokeCap value) override
  {
    rive_paint_cap(m_handle, (uint32_t)value);
  }
  void feather(float value) override { rive_paint_feather(m_handle, value); }
  void blendMode(BlendMode value) override
  {
    rive_paint_blend_mode(m_handle, (uint32_t)value);
  }
  void shader(rcp<RenderShader> value) override;
  void shaderTransform(const Mat2D& value) override
  {
    rive_paint_shader_transform(m_handle, value.values(), 6);
  }
  void invalidateStroke() override {}

  uint32_t handle() const { return m_handle; }

private:
  rcp<RenderShader> m_shader;
  uint32_t m_handle;
};

class ModuleRenderShader : public RenderShader
{
public:
  ModuleRenderShader(uint32_t handle) : m_handle(handle) {}
  ~ModuleRenderShader() override { rive_shader_release(m_handle); }
  uint32_t handle() const { return m_handle; }

private:
  uint32_t m_handle;
};

// Out of line so ModuleRenderShader's handle accessor is visible.
void ModuleRenderPaint::shader(rcp<RenderShader> value)
{
  // Pinned so the host handle outlives the assignment.
  m_shader = value;
  rive_paint_shader(
      m_handle,
      value != nullptr ? static_cast<ModuleRenderShader*>(value.get())->handle()
                       : 0);
}

// Contents live in module memory and push to the host on unmap.
class ModuleRenderBuffer : public RenderBuffer
{
public:
  ModuleRenderBuffer(
      RenderBufferType type,
      RenderBufferFlags flags,
      size_t sizeInBytes)
      : RenderBuffer(type, flags, sizeInBytes)
      , m_handle(rive_buffer_new(
            (uint32_t)type,
            (uint32_t)flags,
            (uint32_t)sizeInBytes))
      , m_store(new uint8_t[sizeInBytes])
  {}
  ~ModuleRenderBuffer() override
  {
    rive_buffer_release(m_handle);
    delete[] m_store;
  }
  uint32_t handle() const { return m_handle; }

protected:
  void* onMap() override { return m_store; }
  void onUnmap() override
  {
    rive_buffer_update(m_handle, m_store, (uint32_t)sizeInBytes());
  }

private:
  uint32_t m_handle;
  uint8_t* m_store;
};

// Instances live in module memory and push to the host on each edit.
class ModuleImageMeshInstances : public ImageMeshInstances
{
public:
  ModuleImageMeshInstances(size_t count)
      : ImageMeshInstances(count)
      , m_handle(rive_mesh_instances_new((uint32_t)count))
      , m_hostCount(count)
  {}
  ~ModuleImageMeshInstances() override
  {
    rive_mesh_instances_release(m_handle);
  }
  uint32_t handle() const { return m_handle; }

protected:
  void onEndEdit() override
  {
    Span<const ImageMeshInstanceData> data = instanceData();
    if (data.size() != m_hostCount)
    {
      rive_mesh_instances_resize(m_handle, (uint32_t)data.size());
      m_hostCount = data.size();
    }
    rive_mesh_instances_update(
        m_handle,
        0,
        reinterpret_cast<const uint8_t*>(data.data()),
        (uint32_t)(data.size() * sizeof(ImageMeshInstanceData)));
  }

private:
  uint32_t m_handle;
  size_t m_hostCount;
};

class ModuleRenderImage : public RenderImage
{
public:
  ModuleRenderImage(uint32_t handle) : m_handle(handle) { refreshSize(); }

  // The host image can still be decoding when it is wrapped (a web
  // runtime, or the CLI preview copying one), so its size is re-read
  // rather than trusted from the wrap.
  void refreshSize()
  {
    m_Width = (int)rive_image_width(m_handle);
    m_Height = (int)rive_image_height(m_handle);
  }
  ~ModuleRenderImage() override { rive_image_release(m_handle); }
  uint32_t handle() const { return m_handle; }

private:
  uint32_t m_handle;
};

class ModuleFactory : public Factory
{
public:
#if defined(RIVE_CANVAS) && defined(RIVE_ORE)
  ore::Context* ore() override { return wasmModuleOreContext(); }
#endif
  rcp<RenderBuffer> makeRenderBuffer(
      RenderBufferType type,
      RenderBufferFlags flags,
      size_t sizeInBytes) override
  {
    return make_rcp<ModuleRenderBuffer>(type, flags, sizeInBytes);
  }
  rcp<ImageMeshInstances> makeImageMeshInstances(size_t count) override
  {
    return make_rcp<ModuleImageMeshInstances>(count);
  }
  rcp<RenderShader> makeLinearGradient(
      float sx,
      float sy,
      float ex,
      float ey,
      const ColorInt colors[],
      const float stops[],
      size_t count) override
  {
    return make_rcp<ModuleRenderShader>(
        rive_shader_linear(sx, sy, ex, ey, colors, stops, (uint32_t)count));
  }
  rcp<RenderShader> makeRadialGradient(
      float cx,
      float cy,
      float radius,
      const ColorInt colors[],
      const float stops[],
      size_t count) override
  {
    return make_rcp<ModuleRenderShader>(
        rive_shader_radial(cx, cy, radius, colors, stops, (uint32_t)count));
  }
  rcp<RenderPath> makeRenderPath(RawPath& rawPath, FillRule rule) override
  {
    return make_rcp<ModuleRenderPath>(rawPath, rule);
  }
  rcp<RenderPath> makeEmptyRenderPath() override
  {
    return make_rcp<ModuleRenderPath>();
  }
  rcp<RenderPaint> makeRenderPaint() override
  {
    return make_rcp<ModuleRenderPaint>();
  }
  rcp<RenderImage> decodeImage(Span<const uint8_t>) override { return nullptr; }
};

class ModuleRenderer : public Renderer
{
public:
  ModuleRenderer(uint32_t handle) : m_handle(handle) {}
  void save() override { rive_renderer_save(m_handle); }
  void restore() override { rive_renderer_restore(m_handle); }
  void transform(const Mat2D& transform) override
  {
    rive_renderer_transform(
        m_handle,
        transform.xx(),
        transform.xy(),
        transform.yx(),
        transform.yy(),
        transform.tx(),
        transform.ty());
  }
  void drawPath(RenderPath* path, RenderPaint* paint) override
  {
    rive_renderer_draw_path(
        m_handle,
        static_cast<ModuleRenderPath*>(path)->sync(),
        static_cast<ModuleRenderPaint*>(paint)->handle());
  }
  void clipPath(RenderPath* path) override
  {
    rive_renderer_clip_path(
        m_handle,
        static_cast<ModuleRenderPath*>(path)->sync());
  }
  void drawImage(
      const RenderImage* image,
      ImageSampler sampler,
      BlendMode blend,
      float opacity) override
  {
    rive_renderer_draw_image(
        m_handle,
        static_cast<const ModuleRenderImage*>(image)->handle(),
        sampler.asKey(),
        (uint32_t)blend,
        opacity);
  }
  void drawImageMesh(
      const RenderImage* image,
      ImageSampler sampler,
      rcp<RenderBuffer> vertices,
      rcp<RenderBuffer> uvCoords,
      rcp<RenderBuffer> indices,
      uint32_t vertexCount,
      uint32_t indexCount,
      BlendMode blend,
      float opacity) override
  {
    rive_renderer_draw_image_mesh(
        m_handle,
        static_cast<const ModuleRenderImage*>(image)->handle(),
        sampler.asKey(),
        static_cast<ModuleRenderBuffer*>(vertices.get())->handle(),
        static_cast<ModuleRenderBuffer*>(uvCoords.get())->handle(),
        static_cast<ModuleRenderBuffer*>(indices.get())->handle(),
        (uint32_t)blend,
        opacity);
  }
  void drawImageMeshInstanced(
      const RenderImage* image,
      ImageSampler sampler,
      rcp<RenderBuffer> vertices,
      rcp<RenderBuffer> uvCoords,
      rcp<RenderBuffer> indices,
      uint32_t vertexCount,
      uint32_t indexCount,
      rcp<ImageMeshInstances> instances) override
  {
    rive_renderer_draw_image_mesh_instanced(
        m_handle,
        static_cast<const ModuleRenderImage*>(image)->handle(),
        sampler.asKey(),
        static_cast<ModuleRenderBuffer*>(vertices.get())->handle(),
        static_cast<ModuleRenderBuffer*>(uvCoords.get())->handle(),
        static_cast<ModuleRenderBuffer*>(indices.get())->handle(),
        static_cast<ModuleImageMeshInstances*>(instances.get())->handle());
  }
  void modulateOpacity(float opacity) override
  {
    rive_renderer_modulate_opacity(m_handle, opacity);
  }
  void modulateColor(ColorInt color, bool replace) override
  {
    rive_renderer_modulate_color(m_handle, color, replace);
  }
  uint32_t handle() const { return m_handle; }

private:
  uint32_t m_handle;
};

} // namespace

namespace rive
{
uint32_t wasmModuleImageHandle(RenderImage* image)
{
  return image != nullptr ? static_cast<ModuleRenderImage*>(image)->handle()
                          : 0;
}

void wasmModuleRefreshImageSize(RenderImage* image)
{
  if (image != nullptr)
  {
    static_cast<ModuleRenderImage*>(image)->refreshSize();
  }
}

Factory* wasmModuleFactory()
{
  static ModuleFactory factory;
  return &factory;
}

std::unique_ptr<Renderer> makeWasmModuleRenderer(uint32_t handle)
{
  return std::make_unique<ModuleRenderer>(handle);
}

uint32_t wasmModuleRendererHandle(Renderer* renderer)
{
  return renderer != nullptr ? static_cast<ModuleRenderer*>(renderer)->handle()
                             : 0;
}

rcp<RenderImage> makeWasmModuleRenderImage(uint32_t handle)
{
  return make_rcp<ModuleRenderImage>(handle);
}
} // namespace rive

#endif
