#pragma once

#include <psemek/cg/dcel.hpp>

namespace psemek::cg
{

	template <typename Point, typename Edge, typename Face, typename Index>
	dcel<Face, Edge, Point, Index> dual(dcel<Point, Edge, Face, Index> const & d)
	{
		dcel<Face, Edge, Point, Index> result;

		result.edges.reserve(d.edges.size());
		for (auto const & e : d.edges)
		{
			result.push_edge(e.data());
			auto & n = result.edges.back();
			n.twin = e.twin;
			n.face = e.origin;
			n.origin = d.edges[e.twin].face;
		}

		for (Index e = 0; e < result.edges.size(); ++e)
		{
			auto next = [&](auto i){ return d.edges[d.edges[i].twin].next; };

			Index i = e, n = next(i);
			for (; n != e; i = n, n = next(n));

			result.edges[e].next = i;
		}

		result.points.reserve(d.faces.size());
		for (auto const & f : d.faces)
		{
			result.push_point(f.data());
			result.points.back().edge = d.edges[f.edge].twin;
		}

		result.faces.reserve(d.points.size());
		for (auto const & p : d.points)
		{
			result.push_face(p.data());
			result.faces.back().edge = p.edge;
		}

		return result;
	}

}
