#pragma once

#include "volumeshop.h"

#include "Color.h"
#include <math.h>

class Compositor
{
public:

	enum Operator
	{
		OPERATOR_OVER,
		OPERATOR_ROVER,
		OPERATOR_IN,
		OPERATOR_RIN,
		OPERATOR_OUT,
		OPERATOR_ROUT,
		OPERATOR_ATOP,
		OPERATOR_RATOP,
		OPERATOR_XOR,
		OPERATOR_PLUS,
		OPERATOR_CUSTOM,
		OPERATOR_RCUSTOM,
	};

	class Custom
	{
	public:
		Custom(const Color &colA, const Color &colB)
		{
			if (colA.GetAlpha() > 0 && colB.GetAlpha() > 0)
				m_colResult = Color(0.0f,1.0f,0.0f,1.0f);
			else
				m_colResult = Color(0.0f,1.0f,0.0f,0.0f);
		};

		~Custom()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class Over
	{
	public:
		Over(const Color &colA, const Color &colB)
		{
			m_colResult = colA * 1.0f + colB * (1.0f - colA.GetNormalizedAlpha());
		};

		~Over()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class In
	{
	public:
		In(const Color &colA, const Color &colB)
		{
			m_colResult = colA * colB.GetNormalizedAlpha() + colB * 0.0f;
		};

		~In()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class Out
	{
	public:
		Out(const Color &colA, const Color &colB)
		{
			m_colResult = colA * (1.0f - colB.GetNormalizedAlpha()) + colB * 0.0f;
		};

		~Out()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class Atop
	{
	public:
		Atop(const Color &colA, const Color &colB)
		{
			m_colResult = colA * (colB.GetNormalizedAlpha()) + colB * (1.0f - colA.GetNormalizedAlpha());
		};

		~Atop()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class Xor
	{
	public:
		Xor(const Color &colA, const Color &colB)
		{
			m_colResult = colA * (1.0f - colB.GetNormalizedAlpha()) + colB * (1.0f - colA.GetNormalizedAlpha());
		};

		~Xor()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	class Plus
	{
	public:
		Plus(const Color &colA, const Color &colB)
		{
			m_colResult = colA * 1.0f + colB * 1.0f;
		};

		~Plus()
		{
		};

		operator const Color () const
		{
			return m_colResult;
		};

	private:
		Color m_colResult;
	};

	Compositor(const Operator & eOperator, const Color & colA, const Color & colB)
	{
		switch (eOperator)
		{
		case OPERATOR_CUSTOM:
			m_colResult = Custom(colA,colB);
			break;

		case OPERATOR_RCUSTOM:
			m_colResult = Custom(colB,colA);
			break;

		case OPERATOR_OVER:
			m_colResult = Over(colA,colB);
			break;

		case OPERATOR_ROVER:
			m_colResult = Over(colB,colA);
			break;

		case OPERATOR_IN:
			m_colResult = In(colA,colB);
			break;

		case OPERATOR_RIN:
			m_colResult = In(colB,colA);
			break;

		case OPERATOR_OUT:
			m_colResult = Out(colA,colB);
			break;

		case OPERATOR_ROUT:
			m_colResult = Out(colB,colA);
			break;

		case OPERATOR_ATOP:
			m_colResult = Atop(colA,colB);
			break;

		case OPERATOR_RATOP:
			m_colResult = Atop(colB,colA);
			break;

		case OPERATOR_XOR:
			m_colResult = Xor(colA,colB);
			break;

		case OPERATOR_PLUS:
			m_colResult = Plus(colA,colB);
			break;
		}
	};

	~Compositor()
	{
	};

	operator const Color () const
	{
		return m_colResult;
	};

	static const Color over(const Color & colA, const Color & colB)
	{
		return Over(colA,colB);
	};

	static const Color in(const Color & colA, const Color & colB)
	{
		return In(colA,colB);
	};

	static const Color out(const Color & colA, const Color & colB)
	{
		return Out(colA,colB);
	};

	static const Color atop(const Color & colA, const Color & colB)
	{
		return Atop(colA,colB);
	};

	static const Color xor(const Color & colA, const Color & colB)
	{
		return Xor(colA,colB);
	};

	static const Color plus(const Color & colA, const Color & colB)
	{
		return Plus(colA,colB);
	};

private:
	Color m_colResult;
};
