/*
#--------------------------------------------------------
# $File: xrick2png.c,v $          
#--------------------------------------------------------
*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

#include "bctypes.h"
#include "xrick2png.h"
#include "png.h"

// For the 3 pics
#include "pics.h"

#include "sprites.h"
#include "tiles.h"

#include "img.h"
#include "img_icon.e"
#include "img_splash.e"

static void _usage()
{
	printf("xrick2png v%s\n\n", VERSION);
	printf("Usage:  xrick2png\n"
		   "Written by Jason Andersen\n"
		   "Copyright (c) 2018 Jason Andersen.\n"
		   "Unauthorized use prohibited\n");

		   exit(1);

} // usage	

//
// Save the RawBMP Pixel Data, as raw IIGS
// framebuffer data
//
void savePixelsGS(MYBMP *pBitmap, const char* pFilename)
{
	FILE* gsfile = fopen( pFilename, "wb" );

	if (gsfile)
	{
		unsigned char* pPixels = pBitmap->map;

		for (int y = 0; y < pBitmap->height; ++y)
		{
			for (int x = 0; x < pBitmap->width; x+=2)
			{
				unsigned char* pPixel = pPixels + (y*pBitmap->width) + x;

				unsigned char GS_PIXEL = 0;
				GS_PIXEL = (pPixel[0] << 4) | (pPixel[1] & 0xF);
				putc(GS_PIXEL, gsfile);
			}
		}

		fclose(gsfile);
	}
	else
	{
		fprintf(stderr,"\nERROR Unable to create output file: %s\n", pFilename);
		exit(1);
	}
}

//
//
//
void savePixelsGSc1(MYBMP *pBitmap, const char* pFilename)
{
	FILE* gsfile = fopen( pFilename, "wb" );

	if (gsfile)
	{
		unsigned char* pPixels = pBitmap->map;

		for (int y = 0; y < pBitmap->height; ++y)
		{
			for (int x = 0; x < pBitmap->width; x+=2)
			{
				unsigned char* pPixel = pPixels + (y*pBitmap->width) + x;

				unsigned char GS_PIXEL = 0;
				GS_PIXEL = (pPixel[0] << 4) | (pPixel[1] & 0xF);
				putc(GS_PIXEL, gsfile);
			}
		}

		for (int idx = 0; idx < 256; ++idx)
		{
			putc(0, gsfile);	// SCBs + Screen holes
		}

		for (int palnum = 0; palnum < 16; ++palnum)
		{
			for (int idx = 0; idx < 16; idx++)
			{
				u16 pixel = 0;

				u16 red   = pBitmap->palette[ (idx * 3)+0 ];
				u16 green = pBitmap->palette[ (idx * 3)+1 ];
				u16 blue  = pBitmap->palette[ (idx * 3)+2 ];

				red>>=4;
				green>>=4;
				blue>>=4;

				{
					// Generate a ramp of colors, so SCB = 0, is black
					// SCB = 15 is faded in
					float scale = palnum / 15.0f;

					if (palnum < 15)
					{
						float fr = scale * red;
						float fg = scale * green;
						float fb = scale * blue;

						red   = fr;
						green = fg;
						blue  = fb;
					}
				}


				pixel |= red << 8;
				pixel |= green << 4;
				pixel |= blue;

				putc(pixel & 0xff, gsfile);
				putc(pixel >> 8, gsfile);
			}
		}

		fclose(gsfile);
	}
	else
	{
		fprintf(stderr,"\nERROR Unable to create output file: %s\n", pFilename);
		exit(1);
	}
}


//
// Save the RawBMP Data as a PNG
//
void savePng(MYBMP *pBitmap, const char* pFilename)
{
	png_structp png_ptr;
	png_infop info_ptr;

	// PNG Stuff
	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL );

	if (!png_ptr)
	{
		fprintf(stderr,"\nERROR unable to png_create_write_struct\n");
		exit(1);
	}

	info_ptr = png_create_info_struct(png_ptr);

	if (!info_ptr)
	{
		png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
		fprintf(stderr,"\nERROR enable to png_create_info_struct\n");
		exit(1);
	}
			
	// Save it as a PNG
	FILE *pngfile = fopen( pFilename, "wb" );
	if (pngfile)
	{
		int idx;
		png_bytep ptr = (png_bytep) pBitmap->map;
	
		png_bytep *row_pointers = png_malloc(png_ptr, pBitmap->height * sizeof(png_bytep));
		
		png_init_io( png_ptr, pngfile );

		png_set_filter( png_ptr, 0, PNG_FILTER_NONE );

		png_set_compression_level( png_ptr, Z_BEST_COMPRESSION );

		if (256 == pBitmap->num_colors)
		{
			png_set_IHDR( png_ptr,
						  info_ptr,
						  pBitmap->width,
						  pBitmap->height,
						  8, /*bit depth*/
						  PNG_COLOR_TYPE_PALETTE,
						  PNG_INTERLACE_NONE,
						  PNG_COMPRESSION_TYPE_DEFAULT,
						  PNG_FILTER_TYPE_DEFAULT );

			png_set_PLTE( png_ptr,
						  info_ptr,
						  (png_color*)pBitmap->palette, // (palette) Array of png color
						  256 );    // (num_palette) number of color entries in palette

			for (idx = 0; idx < pBitmap->height; idx++)
			{
				row_pointers[ idx ] = ptr;
				ptr+= pBitmap->width;	
			}

			png_set_rows(png_ptr, info_ptr, row_pointers);

			png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
		}

		fclose(pngfile);	
	}
	else
	{
		fprintf(stderr,"\nERROR Unable to create output file: %s\n", pFilename);
		exit(1);
	}
}


/*
 * color tables
 */

#ifdef GFXPC
static U8 RED[] = { 0x00, 0x50, 0xf0, 0xf0, 0x00, 0x50, 0xf0, 0xf0 };
static U8 GREEN[] = { 0x00, 0xf8, 0x50, 0xf8, 0x00, 0xf8, 0x50, 0xf8 };
static U8 BLUE[] = { 0x00, 0x50, 0x50, 0x50, 0x00, 0xf8, 0xf8, 0xf8 };
#endif
#ifdef GFXST
static U8 RED[] = { 0x00, 0xd8, 0xb0, 0xf8,
                    0x20, 0x00, 0x00, 0x20,
                    0x48, 0x48, 0x90, 0xd8,
                    0x48, 0x68, 0x90, 0xb0,
                    /* cheat colors */
                    0x50, 0xe0, 0xc8, 0xf8,
                    0x68, 0x50, 0x50, 0x68,
                    0x80, 0x80, 0xb0, 0xe0,
                    0x80, 0x98, 0xb0, 0xc8
};
static U8 GREEN[] = { 0x00, 0x00, 0x6c, 0x90,
                      0x24, 0x48, 0x6c, 0x48,
                      0x6c, 0x24, 0x48, 0x6c,
                      0x48, 0x6c, 0x90, 0xb4,
		      /* cheat colors */
                      0x54, 0x54, 0x9c, 0xb4,
                      0x6c, 0x84, 0x9c, 0x84,
                      0x9c, 0x6c, 0x84, 0x9c,
                      0x84, 0x9c, 0xb4, 0xcc
};
static U8 BLUE[] = { 0x00, 0x00, 0x68, 0x68,
                     0x20, 0xb0, 0xd8, 0x00,
                     0x20, 0x00, 0x00, 0x00,
                     0x48, 0x68, 0x90, 0xb0,
		     /* cheat colors */
                     0x50, 0x50, 0x98, 0x98,
                     0x68, 0xc8, 0xe0, 0x50,
                     0x68, 0x50, 0x50, 0x50,
                     0x80, 0x98, 0xb0, 0xc8};
#endif

//
// Load the Data into the BMP
//
MYBMP* loadPic(U32* pPicData, int width, int height)
{
	MYBMP *pBitmap = (MYBMP*)malloc(sizeof(MYBMP));
	memset(pBitmap, 0, sizeof(MYBMP));

	pBitmap->width  = width;
	pBitmap->height = height;

#ifdef GFXST

	pBitmap->map = (unsigned char*) malloc(width*height);
	pBitmap->num_colors = 256;
	pBitmap->palette = (unsigned char*) malloc(256*3);

	int x; int y; int k;

	unsigned char* pMap = pBitmap->map;

	for (y = 0; y < height; ++y)
	{
		unsigned char *pB = pMap;
		for (x = 0; x < width; x+=8)
		{
			u32 v = *pPicData++;
			for (k = 8; k--; v >>=4)
			{
				pB[k] = v & 0xF;
			}
			pB+=8;
		}
		pMap += width;
	}

	// palette
	memset(pBitmap->palette, 0, 256*3);

	int pIdx = 0;
	for (int idx=0; idx < 32; ++idx)
	{
		pBitmap->palette[pIdx++] = RED[idx];
		pBitmap->palette[pIdx++] = GREEN[idx];
		pBitmap->palette[pIdx++] = BLUE[idx];
	}

#endif

	return pBitmap;
}

MYBMP* loadImage(img_t *pImage)
{
	MYBMP *pBitmap = (MYBMP*)malloc(sizeof(MYBMP));
	memset(pBitmap, 0, sizeof(MYBMP));

	int width  = pImage->w;
	int height = pImage->h;

	pBitmap->width  = width;
	pBitmap->height = height;

	pBitmap->map = (unsigned char*) pImage->pixels;
	pBitmap->num_colors = 256;
	pBitmap->palette = (unsigned char*) malloc(256*3);

	// palette
	memset(pBitmap->palette, 0, 256*3);

	U8* pPal = pBitmap->palette;

	for (int idx = 0; idx < pImage->ncolors; ++idx)
	{
		pPal[0] = pImage->colors[idx].r;
		pPal[1] = pImage->colors[idx].g;
		pPal[2] = pImage->colors[idx].b;
		pPal+=3;
	}

	return pBitmap;
}

//
// Attempt to generate something we can feed into Mr.Sprite, so that
// I don't have to write a sprite compiler
//
MYBMP* toMrSprite(MYBMP* pBitmap, int tileWidth, int tileHeight, bool bTransparent)
{
	// Hi-Jack Color index 255 as the Lasso color       FF0000
	// Hi-Jack Color index 254 as the transparent color 004000

	int tile_count = pBitmap->height / tileHeight;

	// Also print out the colors, that we'll give to Mr. Sprite
	MYBMP *bmp = (MYBMP*)malloc(sizeof(MYBMP));

	int newWidth  = tileWidth+2;
	int newHeight = tileHeight+3;

	bmp->width  = newWidth;
	bmp->height = tile_count * (newHeight);
	bmp->num_colors = 256;
	bmp->palette = (unsigned char*)malloc(256*3);
	// copy orignal palette
	memcpy(bmp->palette, pBitmap->palette, 768);

	// poke in special colors for Mr. Sprite
	bmp->palette[ (254*3) + 0 ] = 0x40;
	bmp->palette[ (254*3) + 1 ] = 0x00;
	bmp->palette[ (254*3) + 2 ] = 0x40;

	bmp->palette[ (255*3) + 0 ] = 0xFF;
	bmp->palette[ (255*3) + 1 ] = 0xFF;
	bmp->palette[ (255*3) + 2 ] = 0x00;

	// allocate, and set transparent
	bmp->map = (unsigned char*) malloc(bmp->width * bmp->height);
	memset(bmp->map, 254, bmp->width * bmp->height);

	// Copy Tile by Tile from source to dest
	for (int idx = 0; idx < tile_count; ++idx)
	{
		unsigned char *pSrc = pBitmap->map + (idx * (tileWidth * tileHeight));
		unsigned char *pDst = bmp->map + (idx * (newWidth * newHeight));

		// Outline Top
		memset(pDst, 0xFF, newWidth);

		// position to the upper left corner
		pDst += (newWidth + 1);

		for (int y = 0; y < tileHeight; ++y)
		{
			// Left Side
			pDst[-1] = 0xFF;
			// Tile line
			memcpy(pDst, pSrc, tileWidth);
			// Right Side
			pDst[tileWidth] = 0xFF;
			pDst+=newWidth;
			pSrc+=tileWidth;
		}

		// Outline bottom
		memset(pDst-1, 0xFF, newWidth);
	}

	// Make Transparent Transparent
	if (bTransparent)
	{
		for (int idx = 0; idx < (newWidth * newHeight * tile_count); ++idx)
		{
			if (0 == bmp->map[idx])
			{
				bmp->map[idx] = 254;
			}
		}
	}

	return bmp;
}

void printColor(unsigned char* pHex)
{
	printf("%02X%02X%02X", pHex[0], pHex[1], pHex[2]);
}

void mrSpriteColors(MYBMP* pBitmap, const char* pName)
{
	printf("%s MrSprite Colors\n", pName);

	printColor(&pBitmap->palette[254*3]);
	printf(" ");
	printColor(&pBitmap->palette[255*3]);
	printf(" ");

	for (int idx = 0; idx < 16; ++idx)
	{
		printColor(&pBitmap->palette[idx*3]);
		printf(" ");
	}

	printf("\n");
}


//
// Parse command line options
//
int main(int argc, char **argv)
{
	MYBMP *pBitmap;

	// Check Arguments
	while (--argc > 0 && (*++argv)[0] == '-')
	{
		*argv+=1;
		 
		if (strcmp("v", *argv) == 0)
		{
			printf("xrick2png v%s\n", VERSION);
			exit(0);
		}
		
		*argv+= strlen(*argv); // skip rest of string
					
	}
	// At this point only one or 2 arguments left
	// unput filename, and output base name

	if (argc) _usage();

	pBitmap = loadPic( pic_haf, 0x140, 0x20 );
	savePng(pBitmap, "haf.png");
	savePixelsGS(pBitmap, "haf.gs");

	pBitmap = loadPic( pic_congrats, 0x140, 0x20 );
	savePng(pBitmap, "congrats.png");
	savePixelsGS(pBitmap, "congrats.gs");

	pBitmap = loadPic( pic_splash, 320, 200 );
	savePng(pBitmap, "splash.png");
	savePixelsGSc1(pBitmap, "splash.c1");

	pBitmap = loadImage( IMG_SPLASH );
	savePng(pBitmap, "img_splash.png");

	pBitmap = loadImage( IMG_ICON );
	savePng(pBitmap, "img_icon.png");

	pBitmap = loadPic((U32*)&sprites_data[0][0], 32, 21 * 0xd6);
	savePng(pBitmap, "sprites_data.png");
	savePixelsGS(pBitmap, "sprites_data.gs");

	pBitmap = toMrSprite(pBitmap, 32, 21, true);
	savePng(pBitmap, "mr_sprites_data.png");
	mrSpriteColors(pBitmap, "mr_sprites_data.png");


	pBitmap = loadPic((U32*)&tiles_data[0][0], 8, 8 * 0x100);
	savePng(pBitmap, "tiles_data0.png");
	savePixelsGS(pBitmap, "tiles_data0.gs");

	pBitmap = loadPic((U32*)&tiles_data[1][0], 8, 8 * 0x100);
	savePng(pBitmap, "tiles_data1.png");
	savePixelsGS(pBitmap, "tiles_data1.gs");

	pBitmap = loadPic((U32*)&tiles_data[2][0], 8, 8 * 0x100);
	savePng(pBitmap, "tiles_data2.png");
	savePixelsGS(pBitmap, "tiles_data2.gs");

//	pBitmap = toMrSprite(pBitmap, 8, 8, false);
//	savePng(pBitmap, "mr_tiles_data.png");
//	mrSpriteColors(pBitmap, "mr_tiles_data.png");

	printf("\nxrick2png - Processing complete.\n");

	return 0;

} // main	


// eof - xrick2png.c

