#include <psemek/vecr/colorizer.hpp>
#include <psemek/math/swizzle.hpp>

namespace psemek::vecr
{

	gfx::color_4f colorize(gfx::color_rgba const & color, math::point<float, 2> const &, sdf_sample const &)
	{
		return gfx::to_colorf(color);
	}

	gfx::color_4f colorize(gradient const & gradient, math::point<float, 2> const & p, sdf_sample const &)
	{
		return gfx::lerp(
			gfx::to_colorf(gradient.color0),
			gfx::to_colorf(gradient.color1),
			math::clamp(sdf(gradient.shape, p).value + 0.5f, {0.f, 1.f})
		);
	}

	gfx::color_4f colorize(lighting const & lighting, math::point<float, 2> const & p, sdf_sample const & sample)
	{
		auto const real_sample = lighting.shape ? sdf(lighting.shape, p) : sample;

		auto normal = math::swizzle<0, 1, -1>(real_sample.gradient * lighting.slope);
		normal[2] = 1.f;
		normal = math::normalized(normal);

		math::vector view{0.f, 0.f, 1.f};

		auto reflected = 2.f * math::dot(normal, lighting.direction) * normal - lighting.direction;

		auto NdotL = math::dot(normal, lighting.direction);
		auto RdotV = math::dot(reflected, view);

		auto lightness = 0.5f + 0.5f * NdotL;

		auto specular = lighting.specular_intensity * std::pow(std::max(0.f, RdotV), lighting.specular_power);

		auto result = gfx::lerp(gfx::to_colorf(lighting.color0), gfx::to_colorf(lighting.color1), lightness);
		result = gfx::lerp(result, gfx::to_colorf(lighting.specular_color), specular);

		return result;
	}

}
