#define   STRICT     
#include <windows.h> 
#include <stdlib.h>  
#include "corona.h"
#include "smoki2dmd.h"

using namespace corona;

#pragma comment(linker, "/DEF:smoki2dmd.def")
#pragma comment(lib, "corona.lib")

typedef unsigned char byte;

int tC,tC2;
short X2,Y2;
short DstX,DstY;
short SrcX,SrcY;

struct Texture
{
    char* File;
    short Width;
    short Height;
    int* Data;
};

Texture* Textures;
short TextureCount;

int* BackBuffer;
short pitch;
short ScreenWidth;
short ScreenHeight;

struct Rect
{
	short Top;
	short Left;
	short Right;
	short Bottom;
};
 
Rect ClippingWindow;

EXP_LONG SMOKI2DMD_SetClippingWindow(int X, int Y, int Width, int Height)
{
	ClippingWindow.Left = X;
	ClippingWindow.Top = Y;
	ClippingWindow.Right = Width;
	ClippingWindow.Bottom = Height;

	return 1;
}

EXP_LONG SMOKI2DMD_RefreshDestination(int* Destination, short Pitch)
{
	pitch = Pitch / 4;
	BackBuffer = Destination;	
    return 1;
}

EXP_LONG SMOKI2DMD_Unload()
{
	delete[] Textures;
	return 1;
}

EXP_LONG SMOKI2DMD_UnloadTexture(short ID)
{
	delete[] Textures[ID].Data;
	Textures[ID].File = "";
	return 1;
}

EXP_LONG SMOKI2DMD_Initialize(int* Destination, short Width, short Height)
{
	ScreenWidth = Width;
	ScreenHeight = Height;

	pitch = Width;

	BackBuffer = Destination;

	ClippingWindow.Right = Width;
	ClippingWindow.Bottom = Height;
    return 1;
}

EXP_LONG SMOKI2DMD_LoadTextureFromFile(char* Filename)
{
	int i,m;
	int CurrentTexture;

	CurrentTexture = -1;
	for(i = 0; i < TextureCount; i++)
	{
		if(strcmp(Filename,Textures[i].File)==0) return i;
		if(strcmp("",Textures[i].File)==0)
		{
			CurrentTexture = i;
		}
	}

	if(CurrentTexture == -1)
	{
			Texture* TempTextures = Textures;
			 
			TextureCount += 1;
			Textures = new Texture[TextureCount];

			for(m = 0; m < TextureCount-1; m++)
			{
			Textures[m] = TempTextures[m]; 
			}

			delete[] TempTextures;
			CurrentTexture = TextureCount -1;
	}

	corona::Image* image = corona::OpenImage(Filename, corona::PF_B8G8R8A8);
	if (!image) {
		return -1;
	}

	Textures[CurrentTexture].File = new char[strlen(Filename)];
	strcpy(Textures[CurrentTexture].File,Filename);

	Textures[CurrentTexture].Width = image->getWidth();
	Textures[CurrentTexture].Height  = image->getHeight();
	
	corona::PixelFormat format = image->getFormat();

	void* pixels = image->getPixels();
	Textures[CurrentTexture].Data = new int[Textures[CurrentTexture].Width * Textures[CurrentTexture].Height];
	memcpy(Textures[CurrentTexture].Data,(int*)pixels,Textures[CurrentTexture].Width * Textures[CurrentTexture].Height * 4);
	
	delete image;

	return CurrentTexture;
}

long conv_RGB(short r,short g,short b)
{
	return long(r|(g<<8)|(b<<16));
}

long conv_RGBA(short r,short g,short b, short a)
{
	return long(r|(g<<8)|(b<<16))|(a<<24);
}

long AlphaColor(int color1,int color2,short alpha)
{
	short r1,r2,g1,g2,b1,b2;
	short r3,g3,b3;

	r1=color1&0xff;
	g1=(color1>>8)&0xff;
	b1=(color1>>16)&0xff;

	r2=color2&0xff;
	g2=(color2>>8)&0xff;
	b2=(color2>>16)&0xff;

	r3 = (alpha*(r1-r2)) / 256 + r2;
	g3 = (alpha*(g1-g2)) / 256 + g2;
	b3 = (alpha*(b1-b2)) / 256 + b2;

    if(r3 < 0)r3 =0;
	if(g3 < 0)g3 =0;
	if(b3 < 0)b3 =0;

	if(r3 > 255)r3 =255;
	if(g3 > 255)g3 =255;
	if(b3 > 255)b3 =255;

	return conv_RGBA(r3,g3,b3,(color1>>24)&0xff);
}

long Overlay(int color, int coloroverlay)
{
	short r1,g1,b1;

	r1=color&0xff;
	g1=(color>>8)&0xff;
	b1=(color>>16)&0xff;

	short r2,g2,b2;

	b2=coloroverlay&0xff;
	g2=(coloroverlay>>8)&0xff;
	r2=(coloroverlay>>16)&0xff;

	short r3,g3,b3;

	r3 = (r1-255) + r2;
	g3 = (g1-255) + g2;
	b3 = (b1-255) + b2;

    if(r3 < 0)r3 =0;
	if(g3 < 0)g3 =0;
	if(b3 < 0)b3 =0;

	if(r3 > 255)r3 =255;
	if(g3 > 255)g3 =255;
	if(b3 > 255)b3 =255;

	return conv_RGBA(r3,g3,b3,(color>>24)&0xff);
}

int rgb2rgba(int src)
{ 
	return long(((src>>16)&0xff)|(((src>>8)&0xff)<<8)|((src&0xff)<<16)|(0xff<<24));	
}

long RenderArrayToArray(int* dstarray, int* srcarray, short x, short y, short sw, short sh, short sx, short sy, short dstimgw, short dstimgh, short srcimgw , short srcimgh,int clrkey , short alpha,int coloroverlay)
{
	if(alpha == 0) return 0;

	for(Y2 = 0; Y2 <= sh -1; Y2++)
	{
		for(X2 = 0; X2 <= sw -1; X2++)
		{
                      
            SrcX = X2 + sx;
            SrcY = Y2 + (srcimgh - sh) - sy;
            DstX = x + X2;
            DstY = y + Y2 + (dstimgh - sh - y * 2);
            
            if(SrcX >= 0 && SrcY >= 0 && DstX >= 0 && DstY >= 0 && SrcX < srcimgw && SrcY < srcimgh && DstX < dstimgw && DstY < dstimgh)
			{
				tC = srcarray[SrcY * srcimgw + SrcX];
            
				if(tC != rgb2rgba(clrkey))
				{

					if(coloroverlay != 16777215)
					{
						tC = Overlay(tC, coloroverlay);
					}
					
					byte alphachannel;
					alphachannel = (tC>>24)&0xff;
					if(alphachannel == 0)continue;
					if(alphachannel > 0 && alphachannel < 255)
					{
						tC2 = dstarray[DstY * pitch + DstX];
						tC = AlphaColor(tC,tC2,alphachannel);
					}

					if(alpha != 0 && alpha != 255)
					{
						tC2 = dstarray[DstY * pitch + DstX];
						tC = AlphaColor(tC, tC2, alpha);
					}

					dstarray[DstY * pitch + DstX] = tC;
				}
			}
		}                            
	}

}

EXP_LONG SMOKI2DMD_RenderTexture(short id, short x, short y, short sw, short sh, short sx, short sy, int clrkey , short alpha,int coloroverlay)
{
	short dstimgw, dstimgh, srcimgw, srcimgh;
	int* srcarray;
	int* dstarray;

	dstimgw = ScreenWidth;
	dstimgh = ScreenHeight;

	srcimgw = Textures[id].Width;
	srcimgh = Textures[id].Height;

	srcarray = Textures[id].Data;
	dstarray = BackBuffer;

	if(sw == -1)sw = srcimgw;
	if(sh == -1)sh = srcimgh;

    if(x + sw < ClippingWindow.Left) return 0;
    if(y + sh < ClippingWindow.Top) return 0;
    if(x > ClippingWindow.Right) return 0;
    if(y > ClippingWindow.Bottom) return 0;
    
    if(x < ClippingWindow.Left)
	{
        sx = sx - (x - ClippingWindow.Left);
        sw = sw + (x - ClippingWindow.Left);
        x = ClippingWindow.Left;
	}

    if(y < ClippingWindow.Top)
	{
        sy = sy - (y - ClippingWindow.Top);
        sh = sh + (y - ClippingWindow.Top);
        y = ClippingWindow.Top;
	}   
    
    if(x > ClippingWindow.Right - sw)
	{
        sw = sw - (sw - (ClippingWindow.Right - x));
	}
    
    if(y > ClippingWindow.Bottom - sh)
	{
        sh = sh - (sh - (ClippingWindow.Bottom - y));
	}

	y = (dstimgh-y)-sh;
	sy = (srcimgh-sy)-sh;

	return RenderArrayToArray(dstarray,srcarray,x,y,sw,sh,sx,sy,dstimgw,dstimgh,srcimgw,srcimgh,clrkey,alpha,coloroverlay);
}

EXP_LONG SMOKI2DMD_ClearArray(int* array1, short sw, short sh, int color)
{
	for(Y2 = 0; Y2 <= sh-1; Y2++)
	{
		for(X2 = 0; X2 <= sw-1; X2++)
		{
			array1[Y2*pitch+X2] = color;
		}
	}

	return 0;
}