#include <malloc.h>
#include "label.h"

#define TEXT_COLOR 0x000000
#define TEXT_SIZE 16

Label::Label() : Widget()
{
	// Set default state
	labelSprite = NULL;
	labelImage = NULL;
	
	// set caption to nothing
	curCaption = NULL;
	
	// x position is left, no centering
	_centered = false;
}

Label::~Label()
{
	// Free images
	if(labelSprite) { delete labelSprite; }
	if(labelImage) { delete labelImage; }
	
	// Free caption
	if(curCaption) { free(curCaption); }
}

void Label::setColor(Color c)
{
	// Remember color
	text.setColor(c);
}

void Label::setFont(const char *font)
{
	// Remember font
	text.setFont(font);
}

void Label::setSize(int size)
{
	// Remember font size
	text.setSize(size);
}

void Label::setCentered(bool centered)
{
	// If no change, don't do anything
	if(centered == _centered) { return; }
	
	if(!centered)
	{
		// Just disable
		_centered = false;
	}
	else
	{
		// Must redraw text
		_centered = true;
		
		// Reblit text
		if(curCaption) { setCaption(curCaption); }
	}
}

void Label::setCaption(const char *caption)
{
	// Kill old images
	if(labelSprite) { delete labelSprite; }
	if(labelImage) { delete labelImage; }
	
	if(caption != curCaption)
	{
		// Kill old storage
		if(curCaption) { free(curCaption); }
		
		// Allocate storage
		curCaption = (char *)malloc(strlen(caption) + 1);
		
		// Copy
		memcpy(curCaption, caption, strlen(caption) + 1);
	}
	
	// Ensure text starts out noncentered
	text.setRenderPosition(0, 0);
	
	// Center text if needed
	if(_centered)
	{
		// Fake render
		text.setBuffer(NULL, _rect.width, _rect.height);		
		text.renderSimple(caption);
		
		// Grab render metrics
		int tWidth = text.getRenderedWidth();
		int tControlWidth = _rect.width - (DEFAULT_X + DEFAULT_X_RIGHT_EDGE);
		
		// Compute and set
		text.setRenderPosition(((tControlWidth - tWidth) / 2), 0);
	}
	
	// Create new image
	labelImage = new DrawableImage();
	labelSprite = new Sprite();
	
	// Line up blit buffer
	labelImage->createImage(_rect.width, _rect.height);
	
	// Create the blit surface
	u8 *blitbuf = (u8 *)memalign(32, _rect.width * _rect.height * 4);
	
	// Ensure no artifacts
	memset(blitbuf, 0, _rect.width * _rect.height * 4);
	
	// Tie blit surface to text renderer
	text.setBuffer(blitbuf, _rect.width, _rect.height);
	
	// Render text
	text.renderSimple(caption);
	
	// Copy to surface
	labelImage->copyBuffer(blitbuf);
	
	// Free blit buffer
	free(blitbuf);
	
	// Set sprite up
	labelSprite->SetImage(labelImage->getImage());
}

void Label::resize(int width, int height)
{	
	// Pad for text display
	width += PADDING;
	
	// Ensure width/height is a multiple of 4
	while(width % 4) { width++; };
	while(height % 4) { height++; };

	// Don't resize if already set to the right size
	if(_rect.width == width && _rect.height == height) { return; }
	
	// Resize widget
	_rect.width = width;
	_rect.height = height;
	
	// Reskin label
	reskin();
}

void Label::draw()
{
	// Grab location including parent
	Rect dLoc = getDimensions();
	
	// Ensure its been captioned
	if(!labelSprite)
	{
		// It hasn't
		return;
	}
	
	// Create a window
	LayerManager manager(1);
	
	// Ensure label appears in the proper place
	labelSprite->SetPosition(dLoc.x, dLoc.y - PADDING);
	
	// Append label to window
	manager.Append(labelSprite);
	
	// Draw to screen
	manager.Draw(settingsManager.getOffsetX(), settingsManager.getOffsetY());
}

void Label::reskin()
{
	// Set up text renderer
	char tFont[256];
	windowManager.getString("Application.Font.Face", tFont, "DejaVu");	
	text.setFont(tFont);
	
	int textSize;
	windowManager.getLong("Application.Font.Size", &textSize, TEXT_SIZE);
	text.setSize(textSize);
	
	uint32_t textColor;
	windowManager.getLongHex("Application.Font.Color", &textColor, TEXT_COLOR);
	text.setColor(Color(textColor));
	
	// Reblit text
	if(curCaption) { setCaption(curCaption); }
}

void Label::setTransparency(int t)
{
	// Limit
	if(t < 0) { t = 0; }
	if(t > 255) { t = 255; }
	
	// Don't do anything if sprite doesn't exist
	if(!labelSprite) { return; }
	
	// Set transparency in libwiisprite
	labelSprite->SetTransparency(t);
}

