/*
	Copyright 2012 bigbiff/Dees_Troy TeamWin
	This file is part of TWRP/TeamWin Recovery Project.

	TWRP is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	TWRP is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include "../data.hpp"

#include <string>

extern "C" {
#include "../twcommon.h"
#include "../minuitwrp/minui.h"
}

#include "rapidxml.hpp"
#include "objects.hpp"

GUIButton::GUIButton(xml_node<>* node)
	: GUIObject(node)
{
	xml_attribute<>* attr;
	xml_node<>* child;

	mButtonImg = NULL;
	mButtonIcon = NULL;
	mButtonLabel = NULL;
	mAction = NULL;
	mRendered = false;
	hasHighlightColor = false;
	renderHighlight = false;
	hasFill = false;

	if (!node)  return;

	// These can be loaded directly from the node
	mButtonLabel = new GUIText(node);
	mAction = new GUIAction(node);

	child = node->first_node("image");
	if (child)
	{
		mButtonImg = new GUIImage(node);
		if (mButtonImg->Render() < 0)
		{
			delete mButtonImg;
			mButtonImg = NULL;
		}
	}
	if (mButtonLabel->Render() < 0)
	{
		delete mButtonLabel;
		mButtonLabel = NULL;
	}
	// Load fill if it exists
	memset(&mFillColor, 0, sizeof(COLOR));
	child = node->first_node("fill");
	if (child)
	{
		attr = child->first_attribute("color");
		if (attr) {
			hasFill = true;
			std::string color = attr->value();
			ConvertStrToColor(color, &mFillColor);
		}
	}
	if (!hasFill && mButtonImg == NULL) {
		LOGERR("No image resource or fill specified for button.\n");
	}

	// The icon is a special case
	child = node->first_node("icon");
	if (child)
	{
		attr = child->first_attribute("resource");
		if (attr)
			mButtonIcon = PageManager::FindResource(attr->value());
	}

	memset(&mHighlightColor, 0, sizeof(COLOR));
	child = node->first_node("highlight");
	if (child) {
		attr = child->first_attribute("color");
		if (attr) {
			hasHighlightColor = true;
			std::string color = attr->value();
			ConvertStrToColor(color, &mHighlightColor);
		}
	}

	int x, y, w, h;
	TextPlacement = TOP_LEFT;
	if (mButtonImg) {
		mButtonImg->GetRenderPos(x, y, w, h);
	} else if (hasFill) {
		LoadPlacement(node->first_node("placement"), &x, &y, &w, &h, &TextPlacement);
	}
	SetRenderPos(x, y, w, h);
	return;
}

GUIButton::~GUIButton()
{
	if (mButtonImg)	 	delete mButtonImg;
	if (mButtonLabel)   delete mButtonLabel;
	if (mAction)		delete mAction;
}

int GUIButton::Render(void)
{
	if (!isConditionTrue())
	{
		mRendered = false;
		return 0;
	}

	int ret = 0;

	if (mButtonImg)	 ret = mButtonImg->Render();
	if (ret < 0)		return ret;
	if (hasFill) {
		gr_color(mFillColor.red, mFillColor.green, mFillColor.blue, mFillColor.alpha);
		gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
	}
	if (mButtonIcon && mButtonIcon->GetResource())
		gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
	if (mButtonLabel) {
		int w, h;
		mButtonLabel->GetCurrentBounds(w, h);
		if (w != mTextW) {
			mTextW = w;
			if (TextPlacement == CENTER_X_ONLY) {
				mTextX = ((mRenderW - mRenderX) / 2);
			} else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
				mTextX = mRenderW + mRenderX + 5;
				mRenderW += mTextW + 5;
			} else {
				mTextX = mRenderX + ((mRenderW - mTextW) / 2);
			}
			mButtonLabel->SetRenderPos(mTextX, mTextY);
		}
		ret = mButtonLabel->Render();
		if (ret < 0)		return ret;
	}
	if (renderHighlight && hasHighlightColor) {
		gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
		gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
	}
	mRendered = true;
	return ret;
}

int GUIButton::Update(void)
{
	if (!isConditionTrue())	return (mRendered ? 2 : 0);
	if (!mRendered)			return 2;

	int ret = 0, ret2 = 0;

	if (mButtonImg)			ret = mButtonImg->Update();
	if (ret < 0)			return ret;

	if (ret == 0)
	{
		if (mButtonLabel) {
			ret2 = mButtonLabel->Update();
			if (ret2 < 0)	return ret2;
			if (ret2 > ret)	ret = ret2;
		}
	}
	else if (ret == 1)
	{
		// The button re-rendered, so everyone else is a render
		if (mButtonIcon && mButtonIcon->GetResource())
			gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
		if (mButtonLabel)   ret = mButtonLabel->Render();
		if (ret < 0)		return ret;
		ret = 1;
	}
	else
	{
		// Aparently, the button needs a background update
		ret = 2;
	}
	return ret;
}

int GUIButton::SetRenderPos(int x, int y, int w, int h)
{
	mRenderX = x;
	mRenderY = y;
	if (w || h)
	{
		mRenderW = w;
		mRenderH = h;
	}

	mIconW = 0;	 mIconH = 0;
	if (mButtonIcon && mButtonIcon->GetResource())
	{
		mIconW = gr_get_width(mButtonIcon->GetResource());
		mIconH = gr_get_height(mButtonIcon->GetResource());
	}

	mTextH = 0;
	mTextW = 0;
	mIconX = mRenderX + ((mRenderW - mIconW) / 2);
	if (mButtonLabel)   mButtonLabel->GetCurrentBounds(mTextW, mTextH);
	if (mTextW)
	{
		if (TextPlacement == CENTER_X_ONLY) {
			mTextX = ((mRenderW - mRenderX) / 2);
		} else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
			mTextX = mRenderW + mRenderX + 5;
			mRenderW += mTextW + 5;
		} else {
			mTextX = mRenderX + ((mRenderW - mTextW) / 2);
		}
	}

	if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH)
	{
		mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2);
		mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
	}
	else
	{
		int divisor = mRenderH - (mIconH + mTextH);
		mIconY = mRenderY + (divisor / 3);
		mTextY = mRenderY + (divisor * 2 / 3) + mIconH;
	}

	if (mButtonLabel)   mButtonLabel->SetRenderPos(mTextX, mTextY);
	if (mAction)		mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
	return 0;
}

int GUIButton::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	static int last_state = 0;

	if (!isConditionTrue())	 return -1;
	if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH || state == TOUCH_RELEASE) {
		if (last_state == 1) {
			last_state = 0;
			if (mButtonLabel != NULL)
				mButtonLabel->isHighlighted = false;
			if (mButtonImg != NULL)
				mButtonImg->isHighlighted = false;
			renderHighlight = false;
			mRendered = false;
		}
	} else {
		if (last_state == 0) {
			last_state = 1;
			DataManager::Vibrate("tw_button_vibrate");
			if (mButtonLabel != NULL)
				mButtonLabel->isHighlighted = true;
			if (mButtonImg != NULL)
				mButtonImg->isHighlighted = true;
			renderHighlight = true;
			mRendered = false;
		}
	}
	if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH)
		return 0;
	return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
}
