#pragma once

#include <psemek/pcg/seamless.hpp>

#include <psemek/gfx/pixmap.hpp>

namespace psemek::pcg
{

	inline gfx::basic_pixmap<math::vector<float, 3>> bump(gfx::pixmap_float const & height_map, seamless_tag)
	{
		gfx::basic_pixmap<math::vector<float, 3>> result(height_map.dims());

		float const dx = 1.f / result.width();
		float const dy = 1.f / result.height();

		for (auto i : result.indices())
		{
			auto ix0 = i;
			ix0[0] = (ix0[0] + result.width() - 1) % result.width();

			auto ix1 = i;
			ix1[0] = (ix1[0] + 1) % result.width();

			auto iy0 = i;
			iy0[1] = (iy0[1] + result.height() - 1) % result.height();

			auto iy1 = i;
			iy1[1] = (iy1[1] + 1) % result.height();

			float h = height_map(i);
			float hx0 = height_map(ix0);
			float hx1 = height_map(ix1);
			float hy0 = height_map(iy0);
			float hy1 = height_map(iy1);

			auto n = math::vector<float, 3>::zero();

			n += math::normalized(math::vector{hx0 - h, 0.f, dx});
			n += math::normalized(math::vector{h - hx1, 0.f, dx});
			n += math::normalized(math::vector{0.f, hy0 - h, dy});
			n += math::normalized(math::vector{0.f, h - hy1, dy});

			result(i) = math::normalized(n);
		}

		return result;
	}

}
