/*
	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;
	if (mButtonIcon)	delete mButtonIcon;
}

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);
}
