#include "stdafx.h"
#include "..\..\stubs.h"
#include "..\..\Minecraft.h"
#include "..\..\Textures.h"
#include "XUI_FontData.h"
#include "..\..\..\Minecraft.World\StringHelpers.h"


#define USE_NEW 0


extern IDirect3DDevice9 *g_pD3DDevice;

int XUI_FontData::getMaxGlyph()
{
	return m_fontData->getFontData()->m_uiGlyphCount;
}

float XUI_FontData::getFontHeight() 
{ 
	return m_fontData->getFontData()->m_uiGlyphHeight; 
}

float XUI_FontData::getFontTopPadding()
{ 
	return 0;
}

float XUI_FontData::getFontBottomPadding()
{
	return 0;
}

float XUI_FontData::getFontYAdvance()
{
	return m_fontData->getFontData()->m_uiGlyphHeight - 1;
}

float XUI_FontData::getFontMaxWidth()
{
	return m_fontData->getFontData()->m_uiGlyphWidth;
}

float XUI_FontData::getMaxDescent()
{ 
	return 0;
}

float XUI_FontData::getMaxAscent()
{
	return m_fontData->getFontData()->m_uiGlyphHeight;
}

int XUI_FontData::getImageWidth()
{
	return m_fontData->getFontData()->m_uiGlyphMapX;
}

int XUI_FontData::getImageHeight()
{
	return m_fontData->getFontData()->m_uiGlyphMapY;
}

float XUI_FontData::SChar::getMinX()
{
	return 0.0f;
}

float XUI_FontData::SChar::getMaxX()
{
	return (float) m_parent->m_fontData->getFontData()->m_uiGlyphWidth;
}

float XUI_FontData::SChar::getMinY()
{
	return 0.0f;
}

float XUI_FontData::SChar::getMaxY()
{
	return 0.0f; //m_parent->m_fontData->getFontData()->m_uiGlyphHeight;
}

float XUI_FontData::SChar::getAdvance()
{
	return (float) m_parent->m_fontData->getWidth(m_glyphId);
}

int XUI_FontData::SChar::getGlyphId()
{
	return m_glyphId;
}

#define USE_NEW_UV 1

int XUI_FontData::SChar::tu1()
{
#if USE_NEW_UV
	int row = 0, col = 0;
	m_parent->m_fontData->getPos(m_glyphId, row, col);
	return col * m_parent->m_fontData->getFontData()->m_uiGlyphWidth;
#else
	return m_parent->m_Glyphs[m_glyphId].tu1;
#endif
}

int XUI_FontData::SChar::tu2()
{
#if USE_NEW_UV
	return tu1() + m_parent->m_fontData->getFontData()->m_uiGlyphWidth;
#else
	return m_parent->m_Glyphs[m_glyphId].tu2;
#endif
}

int XUI_FontData::SChar::tv1()
{
#if USE_NEW_UV
	int row = 0, col = 0;
	m_parent->m_fontData->getPos(m_glyphId, row, col);
	return row * m_parent->m_fontData->getFontData()->m_uiGlyphHeight + 1;
#else
	return m_parent->m_Glyphs[m_glyphId].tv1;
#endif
}

int XUI_FontData::SChar::tv2()
{
#if USE_NEW_UV
	return tv1() + m_parent->m_fontData->getFontData()->m_uiGlyphHeight;
#else
	return m_parent->m_Glyphs[m_glyphId].tv2;
#endif
}

short XUI_FontData::SChar::getOffset()
{
	return 0;
}

short XUI_FontData::SChar::getWAdvance()
{
	return 0;
}

XUI_FontData::SChar XUI_FontData::getChar(const wchar_t strChar)
{
	SChar out;
	out.m_glyphId = m_fontData->getGlyphId((unsigned int) strChar);
	out.m_parent = this;
	return out;
}

//--------------------------------------------------------------------------------------
// Name: XUI_FontData()
// Desc: Constructor
//--------------------------------------------------------------------------------------
XUI_FontData::XUI_FontData()
{
    m_pFontTexture = NULL;
	m_iFontTexture = -1;

    m_dwNumGlyphs = 0L;
    m_Glyphs = NULL;

    m_cMaxGlyph = 0;

    m_dwNestedBeginCount = 0L;
}


//--------------------------------------------------------------------------------------
// Name: ~XUI_FontData()
// Desc: Destructor
//--------------------------------------------------------------------------------------
XUI_FontData::~XUI_FontData()
{
    Destroy();
}


//--------------------------------------------------------------------------------------
// Name: Create()
// Desc: Create the font's internal objects (texture and array of glyph info)
//       using the XPR packed resource file
//--------------------------------------------------------------------------------------
HRESULT XUI_FontData::Create( SFontData &sfontdata )
{
#ifndef _CONTENT_PACKAGE
	app.DebugPrintf("Attempting to load font data for font: '%s'\n", sfontdata.m_strFontName.c_str());
#endif

	BufferedImage *img = new BufferedImage(sfontdata.m_wstrFilename, false, true);
	
	m_iFontTexture = Minecraft::GetInstance()->textures->getTexture(img, C4JRender::TEXTURE_FORMAT_RxGyBzAw, false);

	int imgWidth = img->getWidth(), imgHeight = img->getHeight();
	intArray rawPixels(imgWidth * imgHeight);
    img->getRGB(0, 0, imgWidth, imgHeight, rawPixels, 0, imgWidth);
	delete img;

	m_fontData = new CFontData( sfontdata, rawPixels.data );

	if (rawPixels.data != NULL) delete [] rawPixels.data;

#if 0
	{  // 4J-JEV: Load in FontData (ABC) file, and initialize member variables from it.

	const ULONG_PTR c_ModuleHandle = (ULONG_PTR)GetModuleHandle(NULL);

	//wsprintfW(szResourceLocator,L"section://%X,%s#%s",c_ModuleHandle,L"media", L"media/font/Mojangles_10.abc");
	wsprintfW(szResourceLocator,L"section://%X,%s#%s%s%s",c_ModuleHandle,L"media", L"media/font/",strFontFileName.c_str(),L".abc");

	BYTE *buffer;
	UINT bufferSize;
	hr = XuiResourceLoadAllNoLoc(
         szResourceLocator,
         &buffer,
         &bufferSize
	);
	if( FAILED(hr) ) app.FatalLoadError();

    //return Create( tex, buffer );
	hr = Create( m_iFontTexture, buffer );
	XuiFree(buffer);
	}

		// The ABC's are wrong, so recalc
	// TODO 4J Stu - This isn't going to change every time we run the app, so really the FontMaker tool needs
	// changed, or at the very least the .abc files need pre-processed to store the values we want
	int rowV = 0;
	int rowXOffset = 0;


    for (unsigned int i = 0; i < 299; i++)
	{
		// Translate unprintable characters
		GLYPH_ATTR* pGlyph;

		DWORD letter = m_fontData->getGlyphId(i);
		if( letter == 0 || letter >= 280 ) continue;
		pGlyph = (GLYPH_ATTR*)&m_Glyphs[letter];                 // Get the requested glyph

		// 4J Stu - The original ABC's were generated for a font height that is 1 pixel higher than our cleaned up version
		// We adjust for 1 pixel padding in the y at the top of each box.
		pGlyph->tv1++;

		if( pGlyph->tv1 != rowV )
		{
			rowV = pGlyph->tv1;
			rowXOffset = 0;
		}
		if( pGlyph->wOffset > 0 )
		{
			rowXOffset += pGlyph->wOffset;
			pGlyph->wOffset = 0;
		}

		pGlyph->tu1 -= rowXOffset;
		pGlyph->tu2 -= rowXOffset;

		int x = pGlyph->tu2-1;
		int emptyColumnX = x;
		for (; x >= pGlyph->tu1; x--)
		{
            bool emptyColumn = true;
			for (int y = pGlyph->tv1; y < pGlyph->tv2; y++)
			{
				int rawPix = rawPixels[x + (y*imgWidth)];
                DWORD pixel = rawPixels[x + (y*imgWidth)] & 0xff000000;
                if (pixel > 0) emptyColumn = false;
            }

            if (!emptyColumn && emptyColumnX == pGlyph->tu2-1)
			{
				emptyColumnX = x;
            }
        }
		if(emptyColumnX != pGlyph->tu2-1)
		{
			pGlyph->wWidth = emptyColumnX-pGlyph->tu1;
			pGlyph->wAdvance = pGlyph->wWidth + 1;
		}
    }
#endif

	return S_OK;
}


//--------------------------------------------------------------------------------------
// Name: Create()
// Desc: Create the font's internal objects (texture and array of glyph info)
//--------------------------------------------------------------------------------------
//HRESULT XUI_FontData::Create( D3DTexture* pFontTexture, const VOID* pFontData )
HRESULT XUI_FontData::Create( int iFontTexture, const VOID* pFontData )
{
    // Save a copy of the texture
    //m_pFontTexture = pFontTexture;
#if 0
	m_iFontTexture = iFontTexture;

    // Check version of file (to make sure it matches up with the FontMaker tool)
    const BYTE* pData = static_cast<const BYTE*>(pFontData);
    DWORD dwFileVersion = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_dwFileVersion;

    if( dwFileVersion == ATGFONTFILEVERSION )
    {
        //m_fFontHeight = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontHeight;
        //m_fFontTopPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontTopPadding;
        //m_fFontBottomPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontBottomPadding;
        //m_fFontYAdvance = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontYAdvance;

        // Point to the translator string which immediately follows the 4 floats
        m_cMaxGlyph = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_cMaxGlyph;
  
        WCHAR* translatorTable = const_cast<FontFileHeaderImage_t*>(reinterpret_cast<const FontFileHeaderImage_t *>(pData))->m_TranslatorTable;

		// 4J Stu - This map saves us some memory because the translatorTable is largely empty
		// If we were ever to use >50% of the table then we should store it and use directly rather than the map
		for( unsigned short i = 0; i < m_cMaxGlyph + 1; ++i )
		{
			if( translatorTable[i] == 0 ) continue;
			m_TranslatorMap.insert( unordered_map<wchar_t, unsigned short>::value_type(i, translatorTable[i]) );
		}

        pData += ATGCALCFONTFILEHEADERSIZE( m_cMaxGlyph + 1 );

        // Read the glyph attributes from the file
        m_dwNumGlyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_dwNumGlyphs;
		m_Glyphs = new GLYPH_ATTR[m_dwNumGlyphs];
		memcpy(m_Glyphs, reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_Glyphs, sizeof(GLYPH_ATTR) * m_dwNumGlyphs);

		//m_dwNumGlyphs = m_fontData->getFontData()->m_uiGlyphCount;
    }
    else
    {
		app.DebugPrintf( "Incorrect version number on font file!\n" );
        return E_FAIL;
    }
#endif
    return S_OK;
}


//--------------------------------------------------------------------------------------
// Name: Destroy()
// Desc: Destroy the font object
//--------------------------------------------------------------------------------------
VOID XUI_FontData::Destroy()
{
	if(m_pFontTexture!=NULL)
	{
		m_pFontTexture->Release();
		delete m_pFontTexture;
	}

	m_fontData->release();

    m_pFontTexture = NULL;
    m_dwNumGlyphs = 0L;
    m_cMaxGlyph = 0;
	
    m_dwNestedBeginCount = 0L;
}

/*
FLOAT XUI_FontData::GetCharAdvance( const WCHAR* strChar )
{
	unsigned int uiChar = (unsigned int) *strChar;
	return 0.0f;// m_fontData.getAdvance(m_fontData.getGlyphId(uiChar));
}

FLOAT XUI_FontData::GetCharWidth( const WCHAR* strChar )
{
        return 0.0f;
}

void XUI_FontData::GetCharMetrics( const WCHAR* strChar, XUICharMetrics *xuiMetrics)
{
	unsigned int uiChar = (unsigned int) *strChar;
	unsigned short usGlyph = m_fontData->getGlyphId(uiChar);

	xuiMetrics->fAdvance = m_fontData->getWidth(usGlyph); //.getAdvance(usGlyph) * (float) m_fontData.getFontData()->m_uiGlyphHeight;
	xuiMetrics->fMaxX = (float) m_fontData->getFontData()->m_uiGlyphWidth;
	xuiMetrics->fMinX = 0.0f;
	xuiMetrics->fMaxY = 0;// m_fontData.getFontData()->m_fAscent * (float) m_fontData.getFontData()->m_uiGlyphHeight;
	xuiMetrics->fMinY = 0;//m_fontData.getFontData()->m_fDescent * (float) m_fontData.getFontData()->m_uiGlyphHeight;
}

unsigned short XUI_FontData::getGlyphId(wchar_t character)
		{
	return m_fontData->getGlyphId( (unsigned int) character );
}
*/