#include "CodingUtils.h"

#include <irrlicht.h>

core::rectf CodingUtils::s_subRects[16];
bool CodingUtils::s_isHorizontal = true;

int CodingUtils::getRandomBetween(int aMin, int aMax)
{
	const int diff = aMax - aMin;
	const int randValue = aMin + (rand() % diff);
	return randValue;
}

void CodingUtils::divieRectInHalf(const core::rectf& inRect, core::rectf& outRect1, core::rectf& outRect2, bool divideX)
{
	const float delta = getRandomBetween(30,70) / 100.f;	//Generates a float between 0.30 and 0.70
	
	const float x = inRect.UpperLeftCorner.X;
	const float y = inRect.UpperLeftCorner.Y;
	const float xLen = inRect.getWidth();
	const float yLen = inRect.getHeight();

	if (divideX)
	{
		//Horizontal division
		outRect1.UpperLeftCorner.X = x;
		outRect1.UpperLeftCorner.Y = y;
		outRect1.LowerRightCorner.X = x+(xLen*delta);
		outRect1.LowerRightCorner.Y = y+yLen;

		outRect2.UpperLeftCorner.X = x+(xLen*delta);
		outRect2.UpperLeftCorner.Y = y;
		outRect2.LowerRightCorner.X = x+xLen;
		outRect2.LowerRightCorner.Y = y+yLen;
	}
	else
	{
		//Vertical division
		outRect1.UpperLeftCorner.X = x;
		outRect1.UpperLeftCorner.Y = y;
		outRect1.LowerRightCorner.X = x+xLen;
		outRect1.LowerRightCorner.Y = y+(yLen*delta);

		outRect2.UpperLeftCorner.X = x;
		outRect2.UpperLeftCorner.Y = y+(yLen*delta);
		outRect2.LowerRightCorner.X = x+xLen;
		outRect2.LowerRightCorner.Y = y+yLen;
	}
}

int CodingUtils::calculateSubRects(const core::rectf& inRect, int divisions)
{
	switch (divisions)
	{
	case 0:
		return 0;
	case 1:
		s_subRects[0] = inRect;
		return 1;
	case 2:
		{
			core::rectf outRect1, outRect2;
			divieRectInHalf(inRect, outRect1, outRect2, s_isHorizontal);
			s_subRects[0] = outRect1;
			s_subRects[1] = outRect2;
			s_isHorizontal = !s_isHorizontal;
			return 2; 
		}
	case 3:
		{
			core::rectf outRect1, outRect2, outRect3;
			divieRectInHalf(inRect, outRect1, outRect2, s_isHorizontal);
			s_subRects[0] = outRect2; //outRect1 is not used because it will be divided again
			divieRectInHalf(outRect1, outRect2, outRect3, !s_isHorizontal);
			s_subRects[1] = outRect2; //Yes, outRect2 again! 
			s_subRects[2] = outRect3;
			s_isHorizontal = !s_isHorizontal;
			return 3;
		}
	default:
		{
			core::rectf outRect1, outRect2, outRect3, outRect4;
			divieRectInHalf(inRect, outRect1, outRect4, s_isHorizontal);
			divieRectInHalf(outRect1, outRect2, outRect3, !s_isHorizontal);
			s_subRects[0] = outRect2;
			s_subRects[1] = outRect3;
			divieRectInHalf(outRect4, outRect2, outRect3, !s_isHorizontal);
			s_subRects[2] = outRect2;
			s_subRects[3] = outRect3;
			divieRectInHalf(outRect4, outRect2, outRect3, !s_isHorizontal);
			return 4;
		}
	}
}

const core::rectf* CodingUtils::getSubRectsArray()
{
	return s_subRects;
}

//The idea behind this method is to get an inner rect from the one
//passed in. Ratio is a value from 0 to 1. Though it should not be zero.
core::rectf CodingUtils::shrinkRect(const core::rectf inRect, float ratio)
{
	if (ratio >= 1)
		return inRect;

	if (ratio == 0) 
		return inRect; //Not exactly "right". It is what I want, though.

	const float innerX = inRect.getWidth() * ratio;
	const float dx = (inRect.getWidth() - innerX) * 0.5f;
	const float innerY = inRect.getHeight() * ratio;
	const float dy = (inRect.getHeight() - innerY) * 0.5f;

	const float x = inRect.UpperLeftCorner.X + dx;
	const float y = inRect.UpperLeftCorner.Y + dy;
	const float x2 = x + innerX;
	const float y2 = y + innerY;
	return core::rectf(x,y,x2,y2);
	
}
