#include <stdio.h>
#include <assert.h>
#include "pvr_texture_encoder.h"
#include "file_common.h"
#include "file_dctex.h"

static int convert_size(int size) {
	if (size > 512)
		return 7;
	else if (size > 256)
		return 6;
	else if (size > 128)
		return 5;
	else if (size > 64)
		return 4;
	else if (size > 32)
		return 3;
	else if (size > 16)
		return 2;
	else if (size > 8)
		return 1;
	else
		return 0;

}

void fDtWrite(const PvrTexEncoder *pte, const char *outfname) {
	assert(pte);

	FILE *f = fopen(outfname, "w");
	assert(f);

	unsigned textype = 0;
	textype |= pteHasMips(pte) << FDT_MIPMAP_SHIFT;
	textype |= pteIsCompressed(pte) << FDT_VQ_SHIFT;
	textype |= pte->pixel_format << FDT_PIXEL_FORMAT_SHIFT;
	textype |= !pte->raw_is_twiddled << FDT_NOT_TWIDDLED_SHIFT;

	//If the width is a power of two, we don't need the stride bit set
	textype |= (pteIsStrided(pte) && !IsPow2(pte->w)) << FDT_STRIDE_SHIFT;

	textype |= ((pte->w / 32) & FDT_STRIDE_VAL_MASK) << FDT_STRIDE_VAL_SHIFT;
	textype |= !IsPow2(pte->h) << FDT_PARTIAL_SHIFT;
	textype |= convert_size(pte->w) << FDT_WIDTH_SHIFT;
	textype |= convert_size(pte->h) << FDT_HEIGHT_SHIFT;

	//Include size of header
	unsigned origsize = 32 + CalcTextureSize(pte->w, pte->h, (ptPixelFormat)pte->pixel_format, pteHasMips(pte), pteIsCompressed(pte), pte->codebook_size * 8);
	unsigned size = ROUND_UP_POW2(origsize, 32);
	unsigned paddingamt = size - origsize;
	pteLog(LOG_DEBUG, "File size: %u orig + %u pad = %u total\n", origsize, paddingamt, size);

	WriteFourCC("DcTx", f);
	Write32LE(size, f);
	Write8(0, f);	//Version
	Write8(0, f);	//Header size is (32 bytes / 32 - 1) = 0
	Write8(pteIsCompressed(pte) ? pte->codebook_size - 1 : 0, f);
	Write8(pteIsPalettized(pte) ? pte->palette_size - 1 : 0, f);
	Write16LE(pte->w, f);
	Write16LE(pte->h, f);
	Write32LE(textype, f);
	Write32LE(0, f);
	Write32LE(0, f);
	Write32LE(0, f);

	WritePvrTexEncoder(pte, f, PTEW_FILE_DCTEX_SMALL_VQ, 0);

	//Pad to 32 bytes
	WritePadZero(paddingamt, f);
	fclose(f);

	//Validate resulting file
	unsigned resultsize = FileSize(outfname);
	ErrorExitOn(resultsize != size, "Size of file written for \"%s\" was incorrect. Expected file to be %u bytes, but result was %u bytes.\n", outfname, size, resultsize);

	f = fopen(outfname, "r");
	void *readbuff = malloc(size);
	if (fread(readbuff, size, 1, f) == 1) {
		if (!fDtValidateHeader(readbuff)) {
			pteLog(LOG_WARNING, "**Error validating output for .DT**\n");
		}
	} else {
		pteLog(LOG_WARNING, "**Error reading file during validation check for .DT output**\n");
	}
	fclose(f);
	free(readbuff);
}

