#ifdef WITH_RIVE_SCRIPTING
#include "lua.h"
#include "rive/renderer.hpp"
#include "rive/rive_types.hpp"
#include "rive/shapes/paint/blend_mode.hpp"
#include "rive/shapes/paint/fill.hpp"
#include "rive/shapes/paint/stroke.hpp"
#include "rive/shapes/paint/solid_color.hpp"
#include "rive/shapes/paint/feather.hpp"
#include "lualib.h"
#include "rive/lua/rive_lua_libs.hpp"
#include "rive/factory.hpp"

using namespace rive;

static void readStyle(lua_State* L, ScriptedPaint* paint, int index)
{
  int atom;
  const char* styleName = lua_tostringatom(L, index, &atom);
  if (!styleName)
  {
    luaL_typeerrorL(L, index, lua_typename(L, LUA_TSTRING));
  }
  switch (atom)
  {
    case (int)LuaAtoms::stroke:
      paint->style(RenderPaintStyle::stroke);
      break;
    case (int)LuaAtoms::fill:
      paint->style(RenderPaintStyle::fill);
      break;
    default:
      luaL_error(L, "'%s' is not a valid PaintStyle", styleName);
      break;
  }
}

static void readJoin(lua_State* L, ScriptedPaint* paint, int index)
{
  int atom;
  const char* joinName = lua_tostringatom(L, index, &atom);
  if (!joinName)
  {
    luaL_typeerrorL(L, index, lua_typename(L, LUA_TSTRING));
  }
  switch (atom)
  {
    case (int)LuaAtoms::miter:
      paint->join(StrokeJoin::miter);
      break;
    case (int)LuaAtoms::round:
      paint->join(StrokeJoin::round);
      break;
    case (int)LuaAtoms::bevel:
      paint->join(StrokeJoin::bevel);
      break;
    default:
      luaL_error(L, "'%s' is not a valid StrokeJoin", joinName);
      break;
  }
}

static void readCap(lua_State* L, ScriptedPaint* paint, int index)
{
  int atom;
  const char* capName = lua_tostringatom(L, index, &atom);
  if (!capName)
  {
    luaL_typeerrorL(L, index, lua_typename(L, LUA_TSTRING));
  }
  switch (atom)
  {
    case (int)LuaAtoms::butt:
      paint->cap(StrokeCap::butt);
      break;
    case (int)LuaAtoms::round:
      paint->cap(StrokeCap::round);
      break;
    case (int)LuaAtoms::square:
      paint->cap(StrokeCap::square);
      break;
    default:
      luaL_error(L, "'%s' is not a valid StrokeCap", capName);
      break;
  }
}

BlendMode rive::lua_toblendmode(lua_State* L, int idx)
{
  int atom;
  const char* blendName = lua_tostringatom(L, idx, &atom);
  if (!blendName)
  {
    luaL_typeerrorL(L, idx, lua_typename(L, LUA_TSTRING));
  }
  switch (atom)
  {
    case (int)LuaAtoms::srcOver:
      return BlendMode::srcOver;

    case (int)LuaAtoms::additive:
      return BlendMode::additive;

    case (int)LuaAtoms::screen:
      return BlendMode::screen;

    case (int)LuaAtoms::overlay:
      return BlendMode::overlay;

    case (int)LuaAtoms::darken:
      return BlendMode::darken;

    case (int)LuaAtoms::lighten:
      return BlendMode::lighten;

    case (int)LuaAtoms::colorDodge:
      return BlendMode::colorDodge;

    case (int)LuaAtoms::colorBurn:
      return BlendMode::colorBurn;

    case (int)LuaAtoms::hardLight:
      return BlendMode::hardLight;

    case (int)LuaAtoms::softLight:
      return BlendMode::softLight;

    case (int)LuaAtoms::difference:
      return BlendMode::difference;

    case (int)LuaAtoms::exclusion:
      return BlendMode::exclusion;

    case (int)LuaAtoms::multiply:
      return BlendMode::multiply;

    case (int)LuaAtoms::hue:
      return BlendMode::hue;

    case (int)LuaAtoms::saturation:
      return BlendMode::saturation;

    case (int)LuaAtoms::color:
      return BlendMode::color;

    case (int)LuaAtoms::luminosity:
      return BlendMode::luminosity;

    default:
      luaL_error(L, "'%s' is not a valid BlendMode", blendName);
      return BlendMode::srcOver;
  }
}

static void readBlendMode(lua_State* L, ScriptedPaint* paint, int index)
{
  auto blendMode = lua_toblendmode(L, index);
  paint->blendMode(blendMode);
}

ScriptedPaintData::ScriptedPaintData() {}

ScriptedPaintData::ScriptedPaintData(const ShapePaint* shapePaint)
{
  if (shapePaint->is<Fill>())
  {
    style(RenderPaintStyle::fill);
  }
  else if (shapePaint->is<Stroke>())
  {
    auto stroke = shapePaint->as<Stroke>();
    style(RenderPaintStyle::stroke);
    thickness(stroke->thickness());
    cap((StrokeCap)stroke->cap());
    join((StrokeJoin)stroke->join());
  }
  for (auto& child : shapePaint->children())
  {
    if (child->is<SolidColor>())
    {
      color(child->as<SolidColor>()->colorValue());
      break;
    }
  }
  if (shapePaint->feather())
  {
    feather(shapePaint->feather()->strength());
  }
  blendMode((BlendMode)shapePaint->blendModeValue());
}

ScriptedPaint::ScriptedPaint(Factory* factory)
    : renderPaint(factory->makeRenderPaint())
{}

ScriptedPaint::ScriptedPaint(Factory* factory, const ScriptedPaint& source)
    : ScriptedPaint(factory)
{
  style(source.m_style);
  color(source.m_color);
  thickness(source.m_thickness);
  join(source.m_join);
  cap(source.m_cap);
  feather(source.m_feather);
  blendMode(source.m_blendMode);
  gradient(source.m_gradient);
  gradientTransform(source.m_gradientTransform);
}

static bool paint_set_value(
    lua_State* L,
    ScriptedPaint* renderPaint,
    int keyAtom,
    int valueIndex)
{
  switch (keyAtom)
  {
    case (int)LuaAtoms::style:
      readStyle(L, renderPaint, valueIndex);
      return true;
    case (int)LuaAtoms::join:
      readJoin(L, renderPaint, valueIndex);
      return true;
    case (int)LuaAtoms::cap:
      readCap(L, renderPaint, valueIndex);
      return true;
    case (int)LuaAtoms::thickness:
      renderPaint->thickness(float(luaL_checknumber(L, valueIndex)));
      return true;
    case (int)LuaAtoms::blendMode:
      readBlendMode(L, renderPaint, valueIndex);
      return true;
    case (int)LuaAtoms::feather:
      renderPaint->feather(float(luaL_checknumber(L, valueIndex)));
      return true;
    case (int)LuaAtoms::gradient:
    {
      ScriptedGradient* gradient = lua_torive<ScriptedGradient>(
          L,
          valueIndex,
          true);
      if (gradient != nullptr)
      {
        renderPaint->gradient(gradient->shader);
      }
      else
      {
        renderPaint->gradient(nullptr);
      }
      return true;
    }
    case (int)LuaAtoms::gradientTransform:
    {
      ScriptedMat2D* transform = lua_torive<ScriptedMat2D>(L, valueIndex, true);
      renderPaint->gradientTransform(
          transform != nullptr ? transform->value : Mat2D());
      return true;
    }
    case (int)LuaAtoms::color:
      renderPaint->color(luaL_checkunsigned(L, valueIndex));
      return true;
    default:
      return false;
  }
}

static void setPropertiesFromDefinitionTable(
    lua_State* L,
    ScriptedPaint* scriptedPaint,
    int tableIndex)
{
  luaL_checktype(L, tableIndex, LUA_TTABLE);

  // iterate table
  // Push another reference to the table on top of the stack (so we know
  // where it is, and this function can work for negative, positive and
  // pseudo indices
  lua_pushvalue(L, tableIndex);
  // stack now contains: -1 => table
  lua_pushnil(L);
  // stack now contains: -1 => nil; -2 => table
  while (lua_next(L, -2))
  {
    // stack now contains: -1 => value; -2 => key; -3 => table
    // copy the key so that lua_tostring does not modify the original
    // lua_pushvalue(L, -2);
    // stack now contains: -1 => key; -2 => value; -3 => key; -4 =>
    // table
    int atom;
    const char* key = lua_tostringatom(L, -2, &atom);
    if (key)
    {
      paint_set_value(L, scriptedPaint, atom, -1);
    }
    lua_pop(L, 1);
    // stack now contains: -1 => key; -2 => table
  }
  // stack now contains: -1 => table (when lua_next returns 0 it pops the
  // key but does not push anything.) Pop table
  lua_pop(L, 1);
}

static int paint_new(lua_State* L)
{
  ScriptingContext* context = static_cast<ScriptingContext*>(
      lua_getthreaddata(L));
  lua_newrive<ScriptedPaint>(L, context->factory());

  return 1;
}

static int paint_with(lua_State* L)
{
  ScriptingContext* context = static_cast<ScriptingContext*>(
      lua_getthreaddata(L));
  auto scriptedPaint = lua_newrive<ScriptedPaint>(L, context->factory());
  setPropertiesFromDefinitionTable(L, scriptedPaint, 1);
  return 1;
}

static int paint_newindex(lua_State* L)
{
  int atom;
  const char* key = lua_tostringatom(L, 2, &atom);
  if (!key)
  {
    luaL_typeerrorL(L, 2, lua_typename(L, LUA_TSTRING));
    return 0;
  }

  auto scriptedPaint = lua_torive<ScriptedPaint>(L, 1);
  paint_set_value(L, scriptedPaint, atom, 3);

  return 0;
}

void ScriptedPaintData::pushStyle(lua_State* L)
{
  switch (m_style)
  {
    case RenderPaintStyle::fill:
      lua_pushstring(L, "fill");
      break;
    case RenderPaintStyle::stroke:
      lua_pushstring(L, "stroke");
      break;
    default:
      RIVE_UNREACHABLE();
  }
}

void ScriptedPaintData::pushJoin(lua_State* L)
{
  switch (m_join)
  {
    case StrokeJoin::miter:
      lua_pushstring(L, "miter");
      break;
    case StrokeJoin::bevel:
      lua_pushstring(L, "bevel");
      break;
    case StrokeJoin::round:
      lua_pushstring(L, "round");
      break;
    default:
      RIVE_UNREACHABLE();
  }
}

void ScriptedPaintData::pushCap(lua_State* L)
{
  switch (m_cap)
  {
    case StrokeCap::butt:
      lua_pushstring(L, "butt");
      break;
    case StrokeCap::square:
      lua_pushstring(L, "square");
      break;
    case StrokeCap::round:
      lua_pushstring(L, "round");
      break;
    default:
      RIVE_UNREACHABLE();
  }
}

void ScriptedPaintData::pushThickness(lua_State* L)
{
  lua_pushnumber(L, m_thickness);
}

void ScriptedPaintData::pushBlendMode(lua_State* L)
{
  switch (m_blendMode)
  {
    case BlendMode::srcOver:
      lua_pushstring(L, "srcOver");
      break;
    case BlendMode::additive:
      lua_pushstring(L, "additive");
      break;
    case BlendMode::screen:
      lua_pushstring(L, "screen");
      break;
    case BlendMode::overlay:
      lua_pushstring(L, "overlay");
      break;
    case BlendMode::darken:
      lua_pushstring(L, "darken");
      break;
    case BlendMode::lighten:
      lua_pushstring(L, "lighten");
      break;
    case BlendMode::colorDodge:
      lua_pushstring(L, "colorDodge");
      break;
    case BlendMode::colorBurn:
      lua_pushstring(L, "colorBurn");
      break;
    case BlendMode::hardLight:
      lua_pushstring(L, "hardLight");
      break;
    case BlendMode::softLight:
      lua_pushstring(L, "softLight");
      break;
    case BlendMode::difference:
      lua_pushstring(L, "difference");
      break;
    case BlendMode::exclusion:
      lua_pushstring(L, "exclusion");
      break;
    case BlendMode::multiply:
      lua_pushstring(L, "multiply");
      break;
    case BlendMode::hue:
      lua_pushstring(L, "hue");
      break;
    case BlendMode::saturation:
      lua_pushstring(L, "saturation");
      break;
    case BlendMode::color:
      lua_pushstring(L, "color");
      break;
    case BlendMode::luminosity:
      lua_pushstring(L, "luminosity");
      break;
    default:
      RIVE_UNREACHABLE();
  }
}

void ScriptedPaintData::pushFeather(lua_State* L)
{
  lua_pushnumber(L, m_feather);
}
void ScriptedPaintData::pushGradient(lua_State* L)
{
  if (m_gradient)
  {
    ScriptedGradient* gradient = lua_newrive<ScriptedGradient>(L);
    gradient->shader = m_gradient;
  }
  else
  {
    lua_pushnil(L);
  }
}
void ScriptedPaintData::pushGradientTransform(lua_State* L)
{
  lua_newrive<ScriptedMat2D>(L, m_gradientTransform);
}
void ScriptedPaintData::pushColor(lua_State* L)
{
  lua_pushunsigned(L, m_color);
}

static int paint_index(lua_State* L)
{
  int atom;
  const char* key = lua_tostringatom(L, 2, &atom);
  if (!key)
  {
    luaL_typeerrorL(L, 2, lua_typename(L, LUA_TSTRING));
    return 0;
  }

  auto scriptedPaint = (ScriptedPaintData*)lua_touserdata(L, 1);
  switch (atom)
  {
    case (int)LuaAtoms::style:
      scriptedPaint->pushStyle(L);
      return 1;
    case (int)LuaAtoms::join:
      scriptedPaint->pushJoin(L);
      return 1;
    case (int)LuaAtoms::cap:
      scriptedPaint->pushCap(L);
      return 1;
    case (int)LuaAtoms::thickness:
      scriptedPaint->pushThickness(L);
      return 1;
    case (int)LuaAtoms::blendMode:
      scriptedPaint->pushBlendMode(L);
      return 1;
    case (int)LuaAtoms::feather:
      scriptedPaint->pushFeather(L);
      return 1;
    case (int)LuaAtoms::gradient:
      scriptedPaint->pushGradient(L);
      return 1;
    case (int)LuaAtoms::gradientTransform:
      scriptedPaint->pushGradientTransform(L);
      return 1;
    case (int)LuaAtoms::color:
      scriptedPaint->pushColor(L);
      return 1;
    default:
      return 0;
  }
}

// Direct field getters bypass the __index Lua frame. They are dispatched by
// LOP_GETTABLEKS via global_State::udatadirectfields[tag] when the field-name
// string matches a registered handler. Slow path (paint_index) still handles
// every other field, so anything that returns a string, userdata, or requires
// allocation must NOT be registered here.

static void paint_direct_thickness(void* udata, void* result)
{
  lua_userdatadirectfield_setnumber(
      result,
      ((ScriptedPaintData*)udata)->thickness());
}

static void paint_direct_feather(void* udata, void* result)
{
  lua_userdatadirectfield_setnumber(
      result,
      ((ScriptedPaintData*)udata)->feather());
}

static void paint_direct_color(void* udata, void* result)
{
  // Matches the slow path: lua_pushunsigned stores ColorInt as lua_Number.
  lua_userdatadirectfield_setnumber(
      result,
      (double)((ScriptedPaintData*)udata)->color());
}

static int paint_copy(lua_State* L)
{
  int argCount = lua_gettop(L);

  auto scriptedPaint = lua_torive<ScriptedPaint>(L, 1);

  ScriptingContext* context = static_cast<ScriptingContext*>(
      lua_getthreaddata(L));
  auto scriptedPaintCopy = lua_newrive<ScriptedPaint>(
      L,
      context->factory(),
      *scriptedPaint);

  if (argCount == 2)
  {
    setPropertiesFromDefinitionTable(L, scriptedPaintCopy, 2);
  }
  return 1;
}

static int paint_namecall(lua_State* L)
{
  int atom;
  const char* str = lua_namecallatom(L, &atom);
  if (str != nullptr)
  {
    switch (atom)
    {
      case (int)LuaAtoms::copy:
        return paint_copy(L);
    }
  }

  luaL_error(L, "%s is not a valid method of %s", str, ScriptedMat2D::luaName);
  return 0;
}

static const luaL_Reg paintStaticMethods[] = {
    {"new", paint_new},
    {"with", paint_with},
    {NULL, NULL},
};

static void registerPaintDirectFieldGetters(lua_State* L, int tag)
{
  lua_registeruserdatadirectfieldget(
      L,
      tag,
      "thickness",
      paint_direct_thickness);
  lua_registeruserdatadirectfieldget(L, tag, "feather", paint_direct_feather);
  lua_registeruserdatadirectfieldget(L, tag, "color", paint_direct_color);
}

int luaopen_rive_paint(lua_State* L)
{
  lua_register_rive<ScriptedPaintData>(L);

  lua_pushcfunction(L, paint_index, nullptr);
  lua_setfield(L, -2, "__index");
  lua_setreadonly(L, -1, true);
  lua_pop(L, 1); // pop the metatable

  registerPaintDirectFieldGetters(L, ScriptedPaintData::luaTag);

  luaL_register(L, ScriptedPaint::luaName, paintStaticMethods);
  lua_register_rive<ScriptedPaint>(L);

  lua_pushcfunction(L, paint_index, nullptr);
  lua_setfield(L, -2, "__index");

  lua_pushcfunction(L, paint_newindex, nullptr);
  lua_setfield(L, -2, "__newindex");

  lua_pushcfunction(L, paint_namecall, nullptr);
  lua_setfield(L, -2, "__namecall");

  lua_setreadonly(L, -1, true);
  lua_pop(L, 1); // pop the metatable

  registerPaintDirectFieldGetters(L, ScriptedPaint::luaTag);

  return 1;
}

#endif
