#include "water.h"
#include "math.h"
#include <string.h>

WATER::WATER()
{
	init();
}

WATER::WATER(char *cBackground)
{
	init();
	bBack_Ground = load_bitmap_check(cBackground, NULL);
}

WATER::WATER(char *cBackground, char *cForeground)
{
	init();
	bBack_Ground = load_bitmap_check(cBackground, NULL);
	bWater_Mixture = load_bitmap_check(cForeground, NULL);
}

WATER::~WATER()
{

}

void WATER::load(char *cBackground, char *cForeground)
{
	bBack_Ground = load_bitmap_check(cBackground, NULL);
	bWater_Mixture = load_bitmap_check(cForeground, NULL);
}
void WATER::loadBG(char *cBackground){	bBack_Ground = load_bitmap_check(cBackground, NULL);  }
void WATER::loadFG(char *cForeground){  bWater_Mixture = load_bitmap_check(cForeground, NULL);  }

void WATER::destroy()
{
	int i = 0;
	for(i = 0; i < MAX_DROPS; i++)
		if(dWaves[i] != NULL) delete dWaves[i];

	if(bBack_Ground != NULL) destroy_bitmap(bBack_Ground);
	if(bWater_Mixture != NULL) destroy_bitmap(bWater_Mixture);
	if(bImage != NULL) destroy_bitmap(bImage);
	if(bTransfer != NULL) destroy_bitmap(bTransfer);
	if(bTemp != NULL) destroy_bitmap(bTemp);
}



void WATER::init()
{
	update_timer = 0;
	for (int c=-256; c<256; c++) {
		double d = c/4.0;
		dispLut[c+256] = (unsigned short)((int)(tan(asin(sin(atan(d))/2.0))*d));
	}
		
	for(int i = 0; i < iWidth ; i++)
		for(int j = 0; j < iHeight; j++)
		{
			WaveMap1[i][j] = 0;		
			WaveMap2[i][j] = 0;
			ImageMap[i][j] = 0;
		}

	for(int i = 0; i < MAX_DROPS; i++)
		dWaves[i] = NULL;
	
	iClear = 0;
	Current = 0;
	iTransparency = 0;
	damper = 0;
	smooth = 0;
	cSaturation = 0;
	rushing = false;
	rushing_amount = 0;
	bBack_Ground = NULL;
	bWater_Mixture = NULL;
	bImage = NULL;
	bTransfer = NULL;
	bUnder_Water = NULL;

}

void WATER::Update_Image()
{
	set_trans_blender(0,0,0, iTransparency);
	clear(bTransfer);
	stretch_sprite(bTransfer, bBack_Ground, 0, 0, bTransfer->w, bTransfer->h);
	draw_sprite(bImage, bTransfer, 0, 0);
	draw_sprite(bImage, bUnder_Water, 0, 0);
	clear(bTransfer);
	stretch_sprite(bTransfer, bWater_Mixture, 0, 0, bTransfer->w, bTransfer->h);
	draw_trans_sprite(bImage, bTransfer, 0, 0);
	
}

void WATER::mix()
{	
	Update_Image();
	
	for(int x = 0; x < iWidth; x++)
		for(int y = 0; y < iHeight; y++)
			ImageMap[x][y] = getpixel(bImage, x, y);	
}

void WATER::submerge(BITMAP *bSubmerge, int x, int y, int w, int h)
{
	stretch_sprite(bUnder_Water, bSubmerge, x, y, w, h);	
	Update_Image();
	
	for(int i = x; i < x + w; i++)
		for(int j = y; j < y + h; j++)
			ImageMap[i][j] = getpixel(bImage, i, j);	
}

void WATER::clear_under_water()
{
	rectfill(bUnder_Water, 0, 0, bUnder_Water->w, bUnder_Water->h, MASK);
	Update_Image();
	mix();
}

void WATER::mixture(int iAmount){ iTransparency = MID(0, iAmount, 255); mix();}
int WATER::Get_Transparency(){return iTransparency;}

void WATER::flip()
{
	if(Current == false) Current = true;
	else Current = false;
}

void WATER::Drop(int size){	Drop(rand() % iWidth, rand() % iHeight, size, 1, 0.0); }
void WATER::Drop(int x, int y, int size, int refresh_rate, float decay)
{
	Drop(x, y, size, refresh_rate, decay, false, false, 0);	
}

void WATER::Drop(int x, int y, int size, int refresh_rate, float decay, bool horizontal, bool vertical, int length)
{
	int i = 0;
	DROP *dWave_Temp;
        return;
	if(strcmp(GAME.configuration->level, "LOW") == 0) return; 
	if(strcmp(GAME.configuration->level, "MEDIUM") == 0) size /= 2; 
	//if(abs(WaveMap1[x][y]) > 5000 || abs(WaveMap2[x][y]) > 5000) return;

	while(i < MAX_DROPS && dWaves[i] != NULL)
		i++;	

	if(i == MAX_DROPS) return;

	dWave_Temp = new DROP;
	dWave_Temp->x = x;
	dWave_Temp->y = y;
	dWave_Temp->size = size;
	dWave_Temp->refresh_rate = refresh_rate;
	dWave_Temp->decay = decay;
	dWave_Temp->vertical = vertical;
	dWave_Temp->horizontal = horizontal;
	dWave_Temp->length = length;
	dWave_Temp->timer = 0;

	dWaves[i] = dWave_Temp;
	WaveMap1[dWaves[i]->x][dWaves[i]->y] = dWaves[i]->size;
}

void WATER::Drop(int x, int y, int size)
{
	if(strcmp(GAME.configuration->level, "LOW") == 0) return;
	if(strcmp(GAME.configuration->level, "MEDIUM") == 0) size /= 2;
        if(size > 5000) size = 5000;
	if(x >= 0 && x < iWidth && y >= 0 && y < iHeight)
	WaveMap1[x][y] = size;
}

void WATER::Update()
{
	int x, y, n;
	if(abs(ticks - update_timer) < 1) return;
	update_timer = ticks;

	for(x = 1; x < iWidth - 1 ; x++)
	{
		for(y = 1; y < iHeight - 1; y++)
		{
			//if(WaveMap1[x][y] != 0) allegro_message("there's a drop!");
			if(Current == 0)
			{
				n = (WaveMap1[x-1][y] +
					 WaveMap1[x+1][y] +
					 WaveMap1[x][y-1] +
					 WaveMap1[x][y+1]) / 2 - WaveMap2[x][y];
				if(rushing) n -= (n / rushing_amount);
				else n -= (n >> damper);
				WaveMap2[x][y] = n;					
			}
			else
			{
				n = (WaveMap2[x-1][y] +
					 WaveMap2[x+1][y] +
					 WaveMap2[x][y-1] +
					 WaveMap2[x][y+1]) / 2 - WaveMap1[x][y];
				if(rushing) n -= (n / rushing_amount);
				else n -= (n >> damper);
				WaveMap1[x][y] = n;					
					
			}
		}
	}
	flip();		
	Update_Drops();
}

void WATER::Update_Drops()
{

	//for(i = 0; i < MAX_DROPS; i++)
	//	Update_Drop(i);
}

void WATER::Update_Drop(int i)
{
	int j;
	if(dWaves[i] == NULL) return;
    
	if(abs(ticks - dWaves[i]->timer) > dWaves[i]->refresh_rate && dWaves[i]->size > 2)
	{
		WaveMap1[dWaves[i]->x][dWaves[i]->y] = dWaves[i]->size;
		if(dWaves[i]->vertical)
			for(j = 1; j < dWaves[i]->length; j++)
				if(dWaves[i]->y + j < iHeight)
					WaveMap1[dWaves[i]->x][dWaves[i]->y + j] = dWaves[i]->size;
		if(dWaves[i]->horizontal)
			for(j = 1; j < dWaves[i]->length; j++)
				if(dWaves[i]->x + j < iWidth)
					WaveMap1[dWaves[i]->x + j][dWaves[i]->y] = dWaves[i]->size;

		dWaves[i]->size *= 0;//dWaves[i]->decay;
		dWaves[i]->timer = ticks;
	}			
	if(dWaves[i]->size <= 2)
	{
		delete dWaves[i];
		dWaves[i] = NULL;
	}
	
}
	
void WATER::draw()
{
	int xDiff, yDiff;


	int iRefrac = 0;
	int x, y, xDisplace, yDisplace, newcolor, nx, ny, color_shift;

	Update_Image();	
	
	for(y = 1; y < iHeight; ++y)
	{
		for(x = 1; x < iWidth ; ++x)
		{
			iRefrac = 20;
			if(Current == 0)
			{
				xDiff = WaveMap1[x+1][y] - WaveMap1[x][y];
				yDiff = WaveMap1[x][y+1] - WaveMap1[x][y];
			}
			else
			{
				xDiff = WaveMap2[x+1][y] - WaveMap2[x][y];
				yDiff = WaveMap2[x][y+1] - WaveMap2[x][y];
			}
				
			xDiff = MID(-256, xDiff, 255);
			yDiff = MID(-256, yDiff, 255);
			xDisplace = dispLut[xDiff+256];
			yDisplace = dispLut[yDiff+256];

			xDisplace >>= smooth;
			yDisplace >>= smooth;
			 
			if (xDisplace == 0 || yDisplace == 0) {
				continue;
			}

			iRefrac = 0;
			if(xDiff < 0)
			{
				nx = MID(0, x - xDisplace + iRefrac, iWidth - 1);
				if(yDiff < 0)
					ny = MID(0, y - yDisplace + iRefrac, iHeight - 1);						
				else
					ny = MID(0, y + yDisplace + iRefrac, iHeight - 1);
			}
			else
			{
				nx = MID(0, x + xDisplace + iRefrac, iWidth - 1);
				if(yDiff < 0)
					ny = MID(0, y - yDisplace + iRefrac, iHeight - 1);						
				else
					ny = MID(0, y + yDisplace + iRefrac, iHeight - 1);
			}
			newcolor = ImageMap[nx][ny];
			//if(nx == 0 || nx == (iWidth - 1) || ny == 0 || ny == (POOL_MAXY - 1)) 
			//color_shift = abs(xDisplace + cSaturation + abs(WaveMap1[x][y] / 100));
			//color_shift = xDisplace;
			if(x > 0 && x < bImage->w && y > 0 && y < bImage->h)
				_putpixel32(bImage, x, y, newcolor);
                                //makecol(MID(0, getr32(newcolor) + color_shift, 255), MID(0, getg32(newcolor) + color_shift, 255), MID(0, getb32(newcolor) + color_shift, 255)));
				
		}
	}	
	
}

void WATER::draw(BITMAP *bDisplay)
{
	draw();
	stretch_sprite(bTemp, bImage, 0, 0, bDisplay->w, bDisplay->h);
	set_trans_blender(0,0,0, iClear);
	draw_trans_sprite(bDisplay, bTemp, 0, 0);
	
}
	

void WATER::Setup(int w, int h, int iDamper, int iSmooth, int cleary)
{
	if(bImage != NULL) destroy_bitmap(bImage);
	if(bTransfer != NULL) destroy_bitmap(bTransfer);
	if(bUnder_Water != NULL) destroy_bitmap(bUnder_Water);
	if(bTemp != NULL) destroy_bitmap(bTemp);
	if(strcmp(GAME.configuration->level, "MEDIUM") == 0) 
	{
		w = 100;
		h = 100;
	}
	bImage = create_bitmap_check(w,h);
	bTransfer = create_bitmap_check(w,h);
	bUnder_Water = create_bitmap_check(w,h);
	rectfill(bUnder_Water, 0, 0, bUnder_Water->w, bUnder_Water->h, MASK);
	bTemp = create_bitmap_check(buffer->w, buffer->h);
	mix();
	damper = iDamper;
	smooth = iSmooth;
	iClear = cleary;
	iWidth = w;
	iHeight = h;
	//rushing = true;
	//rushing_amount = 32;
}

