#include "button.h"

#define TEXT_COLOR 0x000000
#define TEXT_SIZE 16

LoadableImage *Button::_image = NULL;
int Button::_instance = 0;

Button::Button() : Widget()
{
	// Ensure no pressing
	_state = 0;
	
	// No false callbacks
	_callbackdown = NULL;
	
	// Figure out instance
	_whichinstance = _instance++;
	
	if(_whichinstance == 0)
	{
		// Only load on first instance
		_image = new LoadableImage;
	}
	
	// Set default state
	_label = new Label;
	
	// Remmeber when divisions change
	_divisions = -1;
	
	// Set up parent/child relationship
	if(_image && _label)
	{
		// Ensures they move together
		_label->move(0, 0);
		_label->setParent(this);
		
		// Ensure centered text
		_label->setCentered(true);
	}
	
	// load by default
	reskin();
}

Button::~Button()
{
	_instance--;
	
	// Free widgets
	if(_instance == 0) { if(_image) { delete _image; } }
	
	if(_label) { delete _label; }
}

void Button::reskin()
{
	// Reload font from theme
	{
		char tFont[256];
		windowManager.getString("Button.Font.Face", tFont, "DejaVu");	
		setFont(tFont);
		
		int textSize;
		windowManager.getLong("Button.Font.Size", &textSize, TEXT_SIZE);
		setSize(textSize);
		
		uint32_t textColor;
		windowManager.getLongHex("Button.Font.Color", &textColor, TEXT_COLOR);
		setColor(Color(textColor));
	}
	
	// Reload other stuff from theme
	{
		// Load image
		if(_whichinstance == 0)
		{
			char bgName[MAXPATHLEN];
			windowManager.getString("Button.BGGraphic", bgName);
			
			// If it fails, oh well its transparent
			if(_image)
			{
				_image->setImage(bgName);
				_image->setDivisions(3);
			}
		}
		
		// Get image dimensions
		Rect tRect = _image->getAbsoluteDimensions();
		
		// Set our own dimensions
		_rect.width = tRect.width;
		_rect.height = tRect.height;
		
		// Set label dimensions to be the same
		if(_label && _rect.width && _rect.height)
		{
			_label->resize(_rect.width, _rect.height);
		}
		
		// Load text offset
		windowManager.getLong("Button.TextOffset", &_offset, 0);		
		if(_label) { _label->move(0, _offset); }
		
		// Load depress hint (images that move when you click them)
		windowManager.getLong("Button.DepressHint", &_depressHint, 0);
	}
	
	// Just invoke child reskins
	if(_label) { _label->reskin(); }
}

void Button::draw()
{
	// Ensure movement is right	
	if(_label) { _label->move(0, ((_state >= 2) ? _depressHint : 0) + _offset); }
	
	// Ensure button is the right state
	if(_image) 
	{ 
		_image->selectDivision(_state > 2 ? 2 : _state); 
		
		// Ensure it moves with this one
		_image->move(0, 0);
		_image->setParent(this);
	}
	
	// Just invoke child draws
	if(_image) { _image->draw(); }
	if(_label) { _label->draw(); }
}

void Button::cursorDown(int x, int y, Action a)
{
	// Only primary click
	if(a != BUTTON_PRIMARY) { return; }
	
	if(_callbackdown)
	{
		// Signal program that the button was pressed
		_callbackdown(_datadown);
	}
	
	// Add clicked state
	_state += 2;
}

void Button::cursorMove(int x, int y)
{
	// Already set hover?
	if(_state & 1) { return; }
	
	// Set hover
	_state++;
}

void Button::cursorUp(int x, int y, Action a)
{
	// Only primary click
	if(a != BUTTON_PRIMARY) { return; }
	
	// Remove clicked state
	_state -=2;
	
	// Ensure we didn't let go after going out of bounds
	if(_state < 0) { _state = 0; }
}

void Button::cursorOut()
{
	// Unset all
	_state = 0;
}

void Button::downCallback(void (*callback)(void *), void *data)
{
	// Set up a callback to fire when pressed
	_callbackdown = callback;
	_datadown = data;
}

void Button::setCaption(const char *caption)
{
	// Don't set caption if there is no label
	if(!_label) { return; }
	
	_label->setCaption(caption);
}

void Button::setColor(Color c)
{
	// Don't set if there is no label
	if(!_label) { return; }
	
	_label->setColor(c);
}

void Button::setFont(const char *font)
{
	// Don't set if there is no label
	if(!_label) { return; }
	
	_label->setFont(font);
}

void Button::setSize(int size)
{
	// Don't set if there is no label
	if(!_label) { return; }
	
	_label->setSize(size);
}

