#include <math.h>
#include "project_volumes.h"
#include "project_textures.h"
#include "fx_colors.h"

unsigned short *fbuffer;
unsigned int fxf_argb[256];

int fxf_fsin1[4096], fxf_fsin2[4096], fxf_fsin3[4096];

int fxf_vsize;
int fxf_vvsize;
int fxf_vvvsize;

#define f_height 2

bool FxFireInit = false;

void InitFxFireColors()
{
    SetPalette(fxf_argb, GetColor(0,0,0,0), GetColor(63,0,127,15), 0, 63);
    SetPalette(fxf_argb, GetColor(63,0,127,16), GetColor(255,127,0,23), 64, 95);
    SetPalette(fxf_argb, GetColor(255,127,0,24), GetColor(255,255,127,63), 96, 191);
    SetPalette(fxf_argb, GetColor(255,255,127,64), GetColor(255,255,255,191), 192, 255);

	GenPalletteTexture(256, fxf_argb);
}

void InitFxFire(Cvolume *vol)
{
	fxf_vsize = vol->GetWidth();
	fxf_vvsize = fxf_vsize * fxf_vsize;
	fxf_vvvsize = fxf_vvsize * fxf_vsize;

	fbuffer = new unsigned short[fxf_vvvsize];

	float l = 0.5f;
    for (int i=0; i<4096; i++)
	{
		fxf_fsin1[i]=(int)(sin(i/(l*15.0))*96.0+96.0);
		fxf_fsin2[i]=(int)(sin(i/(l*20.0))*112.0+112.0);
		fxf_fsin3[i]=(int)(sin(i/(l*35.0))*128.0+128.0);
	}

	InitFxFireColors();

	FxFireInit = true;
}

void FxFireBase(int ticks)
{
    int k = ticks >> 4;
    
    for (int z=0; z<fxf_vsize; z++)
    {
        for (int y=0; y<fxf_vsize/8; y++)
        {
            for (int x=0; x<fxf_vsize; x++)
            {
                unsigned char c = fxf_fsin1[x & 4095] + fxf_fsin2[y & 4095] + fxf_fsin3[z & 4095] + fxf_fsin1[(x+y+k) & 4095] + fxf_fsin2[(x+z+k+k) & 4095] + fxf_fsin3[(y+z+k+k+k) & 4095];
                fbuffer[z * fxf_vvsize + (fxf_vsize - 1 - y) * fxf_vsize + x] = c << f_height;
            }
        }
    }
}

void FxRunFire(Cvolume *vol, int ticks)
{
	if (!FxFireInit) InitFxFire(vol);

	FxFireBase(ticks);

	unsigned int *voxels = vol->GetDataPointer();

    for (int i = 1 + fxf_vsize + fxf_vvsize; i<fxf_vvvsize - 1 - fxf_vsize - fxf_vvsize; i++)
    {
        unsigned short c = ((fbuffer[i] << 1) + (fbuffer[i + fxf_vsize] << 1) + fbuffer[i - 1] + fbuffer[i + 1] + fbuffer[i - fxf_vvsize] + fbuffer[i + fxf_vvsize]) >> 3;
        fbuffer[i] = c;
        c = c >> f_height;
        if (c > 255) c = 255;
        voxels[i] = (unsigned char)c;
    }
}
