#ifndef __Utils_Header_File__
#define __Utils_Header_File__

#include <iostream>
#include <vector>
#include <iterator>
#include <functional>
#include <algorithm>


#define VMATH_NAMESPACE vam
#include "vmath.h"
#include "structs.h"

namespace vam
{
	using namespace std;

	struct ContainsSuperTriangle : public unary_function<const Triangle*,bool>
	{
		int n;
		ContainsSuperTriangle(int n_):n(n_){}

		bool operator()(const Triangle* t)
		{
			return t->containsSuper(n);
		}
	};

	struct UniformPointGenerator
	{
		UniformPointGenerator(float s_):s(s_){}

		Vector2f operator()()
		{
			Vector2f ret(myRand(), myRand());
			return ret;
		}

		float myRand(float s)
		{
			float sign = (rand()%2) ? -1 : 1;
			float val = (rand() % (int)(s * 1000)) * 0.001f;
			return sign * val;
		}

	private:
		float s;

		/**
		 * My random generator - generates pseudo-random number in interval (-s, s)
		 */
		float myRand()
		{
			return myRand(s);

		}
	};

	struct GausianPointGenerator
	{
		GausianPointGenerator(float mx, float my, float v):meanX(mx),meanY(my),variance(v),useLast(false)
		{}

		Vector2f operator()()
		{
			return Vector2f(myRandX(),myRandY());
		}

	private:
		float meanX;
		float meanY;
		float variance;

		bool useLast;
		float y2;

		float myRandInternal()
		{
			float x1, x2, w, y1;
			if (useLast)
			{
				y1 = y2;
				useLast = false;
			}
			else
			{
				do 
				{
					x1 = 2.0f * ranf() - 1.0f;
					x2 = 2.0f * ranf() - 1.0f;
					w = x1 * x1 + x2 * x2;
				} while ( w >= 1.0 );

				w = (float)sqrt( (-2.0 * log( w ) ) / w );
				y1 = x1 * w;
				y2 = x2 * w;
				useLast = true;
			}

			return y1;
		}

		float myRandX()
		{
			return meanX + myRandInternal() * variance;
		}

		float myRandY()
		{
			return meanY + myRandInternal() * variance;
		}

		float ranf()
		{
			return rand()%(1001) * 0.001f;
		}
	};

	struct ForceCCW : public unary_function<Triangle*,void>
	{
		void operator()(Triangle* t)
		{
			t->forceCCWOrient();
		}
	};

	template <class T>
	struct Destroy : public unary_function<T*, void>
	{
		void operator()(T* obj){ delete obj; }
	};

	struct GetAABB : public unary_function<Vector2f,void>
	{
		
		Vector2f& minBox;
		Vector2f& maxBox;
		GetAABB(Vector2f& mn, Vector2f& mx):minBox(mn),maxBox(mx)
		{}

		void operator()(Vector2f v)
		{
			
			
			if (minBox.x > v.x)
			{
				minBox.x = v.x;
			}
			if (minBox.y > v.y)
			{
				minBox.y = v.y;
			}

			if (maxBox.x < v.x)
			{
				maxBox.x = v.x;
			}
			if (maxBox.y < v.y)
			{
				maxBox.y = v.y;
			}
			//cerr << *this << endl;
		}

		friend ostream& operator<<(ostream& ostr, const GetAABB& aabb)
		{
			ostr << "[" << aabb.minBox.x << "," << aabb.minBox.y << "]x[" << aabb.maxBox.x << "," << aabb.maxBox.y << "]";
			return ostr;
		}
	};





	ostream& operator<<(ostream& ostr, const Vector2f& v)
	{
		ostr << v.x << " " << v.y;
		return ostr;
	}

}

#endif //__Utils_Header_File__
	   
