//	World6.cpp - One of the worlds.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation, either version 3 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program.  If not, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#include "World6.h"
#include "Random.h"

//------------------------------------------------------------------------------
World6::World6():
World(ThreeFloats(0.0f/255.0f, 0.0f/255.0f, 0.0f/255.0f),
	  ThreeFloats(218.0f/255.0f, 117.0f/255.0f, 117.0f/255.0f),
	  ThreeFloats(246.0f/255.0f, 84.0f/255.0f, 53.0f/255.0f),
	  ThreeFloats(211.0f/255.0f, 147.0f/255.0f, 154.0f/255.0f),
	  ThreeFloats(1.0f, 0.46f, 0.23f),
	  TwoFloats(2720.0f, -900.0f)),
mousePos(-1.0f),
colourIndex(0),
worldScale(0.1f),
done(false)
{
	int i, j, k, l;
	int correctI[3];
	int correctJ[3];

	desiredColours[0] = getRing1Col();
	desiredColours[1] = getRing2Col();
	desiredColours[2] = getRing3Col();

	for(k=0;k<3;++k)
	{
		bool already = true;

		correctI[k] = (int)(Random::getGlobal().getRandomFloat() * 2.9999f);
		correctJ[k] = (int)(Random::getGlobal().getRandomFloat() * 1.9999f);
		while(already)
		{
			already = false;
			for(l=0;l<k;++l)
			{
				if((correctI[l] == correctI[k]) && (correctJ[l] == correctJ[k]))
				{
					already = true;
					correctI[k] = (int)(Random::getGlobal().getRandomFloat() * 2.9999f);
					correctJ[k] = (int)(Random::getGlobal().getRandomFloat() * 1.9999f);
					break;
				}
			}
		}

		colours[correctJ[k]][correctI[k]][k] = desiredColours[k];

		correctedColours[k].x = 1.0f - colours[correctJ[k]][correctI[k]][k].x;
		correctedColours[k].y = 1.0f - colours[correctJ[k]][correctI[k]][k].y;
		correctedColours[k].z = 1.0f - colours[correctJ[k]][correctI[k]][k].z;

		for(j=0;j<2;++j)
		{
			for(i=0;i<3;++i)
			{
				if(!((i == correctI[k]) && (j == correctJ[k])))
				{
					colours[j][i][k].x = Random::getGlobal().getRandomFloat();
					colours[j][i][k].y = Random::getGlobal().getRandomFloat();
					colours[j][i][k].z = Random::getGlobal().getRandomFloat();
				}
			}
		}

		correctPos[k].x = 64.0f + ((float)correctI[k] * ((1280.0f-128.0f)/2.0f));
		correctPos[k].y = 64.0f + ((float)correctJ[k] * ((720.0f-128.0f)/2.0f));
	}

	mousePos.x = Random::getGlobal().getRandomFloat() * 1280.0f;
	mousePos.y = Random::getGlobal().getRandomFloat() * 720.0f;
	while(mousePos.getDistance(correctPos[0]) < 192.0f)
	{
		mousePos.x = Random::getGlobal().getRandomFloat() * 1280.0f;
		mousePos.y = Random::getGlobal().getRandomFloat() * 720.0f;
	}
	calcColours(0);
}

//------------------------------------------------------------------------------
World6::~World6()
{

}

//------------------------------------------------------------------------------
void World6::mouseMove(const TwoFloats& pos)
{
	if(!done)
	{
		mousePos = pos;
		if(colourIndex < 3)
			calcColours(colourIndex);
	}
}

//------------------------------------------------------------------------------
void World6::subclassTick()
{
	if(colourIndex < 3)
	{
		if(mousePos.getDistance(correctPos[colourIndex]) < 128.0f)
		{
			correctedColours[colourIndex] = desiredColours[colourIndex];

			if((colourIndex == 1) && (worldScale >= 0.35f))
				++colourIndex;
			else if((colourIndex == 2) && (worldScale >= 0.66f))
				++colourIndex;
			else
				++colourIndex;
		}
	}

	switch(colourIndex)
	{
		case 0:
			break;
		case 1:
			if(worldScale < 0.28f)
				worldScale += 0.01f;
			break;
		case 2:
			if(worldScale < 0.46f)
				worldScale += 0.01f;
			break;
		case 3:
			if(worldScale < 0.66f)
				worldScale += 0.01f;
			break;
	}
	setOverallScale(worldScale);

	if(worldScale >= 0.66f)
		done = true;
}

//------------------------------------------------------------------------------
void World6::calcColours(int ring)
{
	TwoFloats tempPos;
	int mouseX, mouseY;
	ThreeFloats topRow;
	ThreeFloats bottomRow;
	ThreeFloats finalCol;

	if(mousePos.x < 64.0f)
		tempPos.x = 0.0f;
	else if(mousePos.x > (1280.0f-64.0f))
		tempPos.x = 2.0f;
	else
		tempPos.x = (2.0f*(mousePos.x-64.0f)/(1280.0f-128.0f));

	if(mousePos.y < 64.0f)
		tempPos.y = 0.0f;
	else if(mousePos.y > (720.0f-64.0f))
		tempPos.y = 1.0f;
	else
		tempPos.y = (mousePos.y-64.0f)/(720.0f-128.0f);

	mouseX = (int)tempPos.x;
	mouseY = (int)tempPos.y;

	tempPos.x -= (float)mouseX;
	tempPos.y -= (float)mouseY;

	if(tempPos.x == 0.0f)
		topRow = colours[mouseY][mouseX][ring];
	else
	{
		topRow = colours[mouseY][mouseX][ring] * (1.0f-tempPos.x);
		topRow += colours[mouseY][mouseX+1][ring] * tempPos.x;
	}

	if(tempPos.y == 0.0f)
	{
		switch(ring)
		{
			case 0:
				correctedColours[0] = topRow;
				break;
			case 1:
				correctedColours[1] = topRow;
				break;
			case 2:
				correctedColours[2] = topRow;
				break;
		}
		setRingColours(correctedColours);
	}
	else
	{
		if(tempPos.x == 0.0f)
			bottomRow = colours[mouseY+1][mouseX][ring];
		else
		{
			bottomRow = colours[mouseY+1][mouseX][ring] * (1.0f-tempPos.x);
			bottomRow += colours[mouseY+1][mouseX+1][ring] * tempPos.x;
		}

		finalCol = topRow * (1.0f-tempPos.y);
		finalCol += bottomRow * tempPos.y;

		switch(ring)
		{
			case 0:
				correctedColours[0] = finalCol;
				break;
			case 1:
				correctedColours[1] = finalCol;
				break;
			case 2:
				correctedColours[2] = finalCol;
				break;
		}
		setRingColours(correctedColours);
	}
}
