/*
	Copyright 2013 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/>.
*/

// pages.cpp - Source to manage GUI base objects

#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 <dirent.h>
#include "../twrp-functions.hpp"
#include "../partitions.hpp"

#include <string>
#include <algorithm>


#include <ziparchive/zip_archive.h>
#include "ZipUtil.h"

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

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

// version 2 requires theme to handle power button as action togglebacklight
// version 4 adds fastbootd support
#define TW_THEME_VERSION 4

#define TW_THEME_VER_ERR -2

extern int gGuiRunning;

std::map<std::string, PageSet*> PageManager::mPageSets;
PageSet* PageManager::mCurrentSet;
MouseCursor *PageManager::mMouseCursor = NULL;
HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
bool PageManager::mReloadTheme = false;
std::string PageManager::mStartPage = "main";
std::vector<language_struct> Language_List;

int tw_x_offset = 0;
int tw_y_offset = 0;
int tw_w_offset = 0;
int tw_h_offset = 0;

// Helper routine to convert a string to a color declaration
int ConvertStrToColor(std::string str, COLOR* color)
{
	// Set the default, solid black
	memset(color, 0, sizeof(COLOR));
	color->alpha = 255;

	// Translate variables
	DataManager::GetValue(str, str);

	// Look for some defaults
	if (str == "black")		return 0;
	else if (str == "white")	{ color->red = color->green = color->blue = 255; return 0; }
	else if (str == "red")		{ color->red = 255; return 0; }
	else if (str == "green")	{ color->green = 255; return 0; }
	else if (str == "blue")		{ color->blue = 255; return 0; }

	// At this point, we require an RGB(A) color
	if (str[0] != '#')
		return -1;

	str.erase(0, 1);

	int result;
	if (str.size() >= 8) {
		// We have alpha channel
		string alpha = str.substr(6, 2);
		result = strtol(alpha.c_str(), NULL, 16);
		color->alpha = result & 0x000000FF;
		str.resize(6);
		result = strtol(str.c_str(), NULL, 16);
		color->red = (result >> 16) & 0x000000FF;
		color->green = (result >> 8) & 0x000000FF;
		color->blue = result & 0x000000FF;
	} else {
		result = strtol(str.c_str(), NULL, 16);
		color->red = (result >> 16) & 0x000000FF;
		color->green = (result >> 8) & 0x000000FF;
		color->blue = result & 0x000000FF;
	}
	return 0;
}

// Helper APIs
xml_node<>* FindNode(xml_node<>* parent, const char* nodename, int depth /* = 0 */)
{
	if (!parent)
		return NULL;

	xml_node<>* child = parent->first_node(nodename);
	if (child)
		return child;

	if (depth == 10) {
		LOGERR("Too many style loops detected.\n");
		return NULL;
	}

	xml_node<>* style = parent->first_node("style");
	if (style) {
		while (style) {
			if (!style->first_attribute("name")) {
				LOGERR("No name given for style.\n");
				continue;
			} else {
				std::string name = style->first_attribute("name")->value();
				xml_node<>* node = PageManager::FindStyle(name);

				if (node) {
					// We found the style that was named
					xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
					if (stylenode)
						return stylenode;
				}
			}
			style = style->next_sibling("style");
		}
	} else {
		// Search for stylename in the parent node <object type="foo" style="foo2">
		xml_attribute<>* attr = parent->first_attribute("style");
		// If no style is found anywhere else and the node wasn't found in the object itself
		// as a special case we will search for a style that uses the same style name as the
		// object type, so <object type="button"> would search for a style named "button"
		if (!attr)
			attr = parent->first_attribute("type");
		// if there's no attribute type, the object type must be the element name
		std::string stylename = attr ? attr->value() : parent->name();
		xml_node<>* node = PageManager::FindStyle(stylename);
		if (node) {
			xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
			if (stylenode)
				return stylenode;
		}
	}
	return NULL;
}

std::string LoadAttrString(xml_node<>* element, const char* attrname, const char* defaultvalue)
{
	if (!element)
		return defaultvalue;

	xml_attribute<>* attr = element->first_attribute(attrname);
	return attr ? attr->value() : defaultvalue;
}

int LoadAttrInt(xml_node<>* element, const char* attrname, int defaultvalue)
{
	string value = LoadAttrString(element, attrname);
	// resolve variables
	DataManager::GetValue(value, value);
	return value.empty() ? defaultvalue : atoi(value.c_str());
}

int LoadAttrIntScaleX(xml_node<>* element, const char* attrname, int defaultvalue)
{
	return scale_theme_x(LoadAttrInt(element, attrname, defaultvalue));
}

int LoadAttrIntScaleY(xml_node<>* element, const char* attrname, int defaultvalue)
{
	return scale_theme_y(LoadAttrInt(element, attrname, defaultvalue));
}

COLOR LoadAttrColor(xml_node<>* element, const char* attrname, bool* found_color, COLOR defaultvalue)
{
	string value = LoadAttrString(element, attrname);
	*found_color = !value.empty();
	// resolve variables
	DataManager::GetValue(value, value);
	COLOR ret = defaultvalue;
	if (ConvertStrToColor(value, &ret) == 0)
		return ret;
	else
		return defaultvalue;
}

COLOR LoadAttrColor(xml_node<>* element, const char* attrname, COLOR defaultvalue)
{
	bool found_color = false;
	return LoadAttrColor(element, attrname, &found_color, defaultvalue);
}

FontResource* LoadAttrFont(xml_node<>* element, const char* attrname)
{
	std::string name = LoadAttrString(element, attrname, "");
	if (name.empty())
		return NULL;
	else
		return PageManager::GetResources()->FindFont(name);
}

ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname)
{
	std::string name = LoadAttrString(element, attrname, "");
	if (name.empty())
		return NULL;
	else
		return PageManager::GetResources()->FindImage(name);
}

AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname)
{
	std::string name = LoadAttrString(element, attrname, "");
	if (name.empty())
		return NULL;
	else
		return PageManager::GetResources()->FindAnimation(name);
}

bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, Placement* placement /* = NULL */)
{
	if (!node)
		return false;

	if (node->first_attribute("x"))
		*x = LoadAttrIntScaleX(node, "x") + tw_x_offset;

	if (node->first_attribute("y"))
		*y = LoadAttrIntScaleY(node, "y") + tw_y_offset;

	if (w && node->first_attribute("w"))
		*w = LoadAttrIntScaleX(node, "w");

	if (h && node->first_attribute("h"))
		*h = LoadAttrIntScaleY(node, "h");

	if (placement && node->first_attribute("placement"))
		*placement = (Placement) LoadAttrInt(node, "placement");

	return true;
}

int ActionObject::SetActionPos(int x, int y, int w, int h)
{
	if (x < 0 || y < 0)
		return -1;

	mActionX = x;
	mActionY = y;
	if (w || h)
	{
		mActionW = w;
		mActionH = h;
	}
	return 0;
}

Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates)
{
	mTouchStart = NULL;

	// We can memset the whole structure, because the alpha channel is ignored
	memset(&mBackground, 0, sizeof(COLOR));

	// With NULL, we make a console-only display
	if (!page)
	{
		mName = "console";

		GUIConsole* element = new GUIConsole(NULL);
		mRenders.push_back(element);
		mActions.push_back(element);
		return;
	}

	if (page->first_attribute("name"))
		mName = page->first_attribute("name")->value();
	else
	{
		LOGERR("No page name attribute found!\n");
		return;
	}

	LOGINFO("Loading page %s\n", mName.c_str());

	// This is a recursive routine for template handling
	ProcessNode(page, templates, 0);
}

Page::~Page()
{
	for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
		delete *itr;
}

bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates, int depth)
{
	if (depth == 10)
	{
		LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
		return false;
	}

	for (xml_node<>* child = page->first_node(); child; child = child->next_sibling())
	{
		std::string type = child->name();

		if (type == "background") {
			mBackground = LoadAttrColor(child, "color", COLOR(0,0,0,0));
			continue;
		}

		if (type == "object") {
			// legacy format : <object type="...">
			xml_attribute<>* attr = child->first_attribute("type");
			type = attr ? attr->value() : "*unspecified*";
		}

		if (type == "text")
		{
			GUIText* element = new GUIText(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "image")
		{
			GUIImage* element = new GUIImage(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
		}
		else if (type == "fill")
		{
			GUIFill* element = new GUIFill(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
		}
		else if (type == "action")
		{
			GUIAction* element = new GUIAction(child);
			mObjects.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "console")
		{
			GUIConsole* element = new GUIConsole(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "terminal")
		{
			GUITerminal* element = new GUITerminal(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
			mInputs.push_back(element);
		}
		else if (type == "button")
		{
			GUIButton* element = new GUIButton(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "checkbox")
		{
			GUICheckbox* element = new GUICheckbox(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "fileselector")
		{
			GUIFileSelector* element = new GUIFileSelector(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "animation")
		{
			GUIAnimation* element = new GUIAnimation(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
		}
		else if (type == "progressbar")
		{
			GUIProgressBar* element = new GUIProgressBar(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "slider")
		{
			GUISlider* element = new GUISlider(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "slidervalue")
		{
			GUISliderValue *element = new GUISliderValue(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "listbox")
		{
			GUIListBox* element = new GUIListBox(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "keyboard")
		{
			GUIKeyboard* element = new GUIKeyboard(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "input")
		{
			GUIInput* element = new GUIInput(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
			mInputs.push_back(element);
		}
		else if (type == "partitionlist")
		{
			GUIPartitionList* element = new GUIPartitionList(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "patternpassword")
		{
			GUIPatternPassword* element = new GUIPatternPassword(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "textbox")
		{
			GUITextBox* element = new GUITextBox(child);
			mObjects.push_back(element);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "template")
		{
			if (!templates || !child->first_attribute("name"))
			{
				LOGERR("Invalid template request.\n");
			}
			else
			{
				std::string name = child->first_attribute("name")->value();
				xml_node<>* node;
				bool node_found = false;

				// We need to find the correct template
				for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
					node = (*itr)->first_node("template");

					while (node)
					{
						if (!node->first_attribute("name"))
							continue;

						if (name == node->first_attribute("name")->value())
						{
							if (!ProcessNode(node, templates, depth + 1))
								return false;
							else {
								node_found = true;
								break;
							}
						}
						if (node_found)
							break;
						node = node->next_sibling("template");
					}
					// [check] why is there no if (node_found) here too?
				}
			}
		}
		else
		{
			LOGERR("Unknown object type: %s.\n", type.c_str());
		}
	}
	return true;
}

int Page::Render(void)
{
	// Render background
	gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
	gr_fill(0, 0, gr_fb_width(), gr_fb_height());

	// Render remaining objects
	std::vector<RenderObject*>::iterator iter;
	for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
	{
		if ((*iter)->Render())
			LOGERR("A render request has failed.\n");
	}
	return 0;
}

int Page::Update(void)
{
	int retCode = 0;

	std::vector<RenderObject*>::iterator iter;
	for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
	{
		int ret = (*iter)->Update();
		if (ret < 0)
			LOGERR("An update request has failed.\n");
		else if (ret > retCode)
			retCode = ret;
	}

	return retCode;
}

int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	// By default, return 1 to ignore further touches if nobody is listening
	int ret = 1;

	// Don't try to handle a lack of handlers
	if (mActions.size() == 0)
		return ret;

	// We record mTouchStart so we can pass all the touch stream to the same handler
	if (state == TOUCH_START)
	{
		std::vector<ActionObject*>::reverse_iterator iter;
		// We work backwards, from top-most element to bottom-most element
		for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
		{
			if ((*iter)->IsInRegion(x, y))
			{
				mTouchStart = (*iter);
				ret = mTouchStart->NotifyTouch(state, x, y);
				if (ret >= 0)
					break;
				mTouchStart = NULL;
			}
		}
	}
	else if (state == TOUCH_RELEASE && mTouchStart != NULL)
	{
		ret = mTouchStart->NotifyTouch(state, x, y);
		mTouchStart = NULL;
	}
	else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
	{
		ret = mTouchStart->NotifyTouch(state, x, y);
	}
	return ret;
}

int Page::NotifyKey(int key, bool down)
{
	std::vector<ActionObject*>::reverse_iterator iter;

	int ret = 1;
	// We work backwards, from top-most element to bottom-most element
	for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
	{
		ret = (*iter)->NotifyKey(key, down);
		if (ret == 0)
			return 0;
		if (ret < 0) {
			LOGERR("An action handler has returned an error\n");
			ret = 1;
		}
	}
	return ret;
}

int Page::NotifyCharInput(int ch)
{
	std::vector<InputObject*>::reverse_iterator iter;

	// We work backwards, from top-most element to bottom-most element
	for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
	{
		int ret = (*iter)->NotifyCharInput(ch);
		if (ret == 0)
			return 0;
		else if (ret < 0)
			LOGERR("A char input handler has returned an error\n");
	}
	return 1;
}

int Page::SetKeyBoardFocus(int inFocus)
{
	std::vector<InputObject*>::reverse_iterator iter;

	// We work backwards, from top-most element to bottom-most element
	for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
	{
		int ret = (*iter)->SetInputFocus(inFocus);
		if (ret == 0)
			return 0;
		else if (ret < 0)
			LOGERR("An input focus handler has returned an error\n");
	}
	return 1;
}

void Page::SetPageFocus(int inFocus)
{
	// Render remaining objects
	std::vector<RenderObject*>::iterator iter;
	for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
		(*iter)->SetPageFocus(inFocus);

	return;
}

int Page::NotifyVarChange(std::string varName, std::string value)
{
	std::vector<GUIObject*>::iterator iter;
	for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
	{
		if ((*iter)->NotifyVarChange(varName, value))
			LOGERR("An action handler errored on NotifyVarChange.\n");
	}
	return 0;
}


// transient data for loading themes
struct LoadingContext
{
	ZipArchiveHandle zip; // zip to load theme from, or NULL for the stock theme
	std::set<std::string> filenames; // to detect cyclic includes
	std::string basepath; // if zip is NULL, base path to load includes from with trailing slash, otherwise empty
	std::vector<xml_document<>*> xmldocs; // all loaded xml docs
	std::vector<char*> xmlbuffers; // text buffers with xml content
	std::vector<xml_node<>*> styles; // refer to <styles> nodes inside xmldocs
	std::vector<xml_node<>*> templates; // refer to <templates> nodes inside xmldocs

	LoadingContext()
	{
		zip = NULL;
	}

	~LoadingContext()
	{
		// free all xml buffers
		for (std::vector<char*>::iterator it = xmlbuffers.begin(); it != xmlbuffers.end(); ++it)
			free(*it);
	}

};

// for FindStyle
LoadingContext* PageManager::currentLoadingContext = NULL;


PageSet::PageSet()
{
	mResources = new ResourceManager;
	mCurrentPage = NULL;

	set_scale_values(1, 1); // Reset any previous scaling values
}

PageSet::~PageSet()
{
	mOverlays.clear();
	for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
		delete *itr;

	delete mResources;
}

int PageSet::Load(LoadingContext& ctx, const std::string& filename)
{
	bool isMain = ctx.xmlbuffers.empty(); // if we have no files yet, remember that this is the main XML file

	if (!ctx.filenames.insert(filename).second)
		// ignore already loaded files to prevent crash with cyclic includes
		return 0;

	// load XML into buffer
	char* xmlbuffer = PageManager::LoadFileToBuffer(filename, ctx.zip);
	if (!xmlbuffer)
		return -1; // error already displayed by LoadFileToBuffer
	ctx.xmlbuffers.push_back(xmlbuffer);

	// parse XML
	xml_document<>* doc = new xml_document<>();
	doc->parse<0>(xmlbuffer);
	ctx.xmldocs.push_back(doc);

	xml_node<>* root = doc->first_node("recovery");
	if (!root)
		root = doc->first_node("install");
	if (!root) {
		LOGERR("Unknown root element in %s\n", filename.c_str());
		return -1;
	}

	if (isMain) {
		int rc = LoadDetails(ctx, root);
		if (rc != 0)
			return rc;
	}

	LOGINFO("Loading resources...\n");
	xml_node<>* child = root->first_node("resources");
	if (child)
		mResources->LoadResources(child, ctx.zip, "theme");

	LOGINFO("Loading variables...\n");
	child = root->first_node("variables");
	if (child)
		LoadVariables(child);

	LOGINFO("Loading mouse cursor...\n");
	child = root->first_node("mousecursor");
	if (child)
		PageManager::LoadCursorData(child);

	LOGINFO("Loading pages...\n");
	child = root->first_node("templates");
	if (child)
		ctx.templates.push_back(child);

	child = root->first_node("styles");
	if (child)
		ctx.styles.push_back(child);

	// Load pages
	child = root->first_node("pages");
	if (child) {
		if (LoadPages(ctx, child)) {
			LOGERR("PageSet::Load returning -1\n");
			return -1;
		}
	}

	// process includes recursively
	child = root->first_node("include");
	if (child) {
		xml_node<>* include = child->first_node("xmlfile");
		while (include != NULL) {
			xml_attribute<>* attr = include->first_attribute("name");
			if (!attr) {
				LOGERR("Skipping include/xmlfile with no name\n");
				continue;
			}

			string filename = ctx.basepath + attr->value();
			LOGINFO("Including file: %s...\n", filename.c_str());
			int rc = Load(ctx, filename);
			if (rc != 0)
				return rc;

			include = include->next_sibling("xmlfile");
		}
	}

	return 0;
}

void PageSet::MakeEmergencyConsoleIfNeeded()
{
	if (mPages.empty()) {
		mCurrentPage = new Page(NULL, NULL); // fallback console page
		// TODO: since removal of non-TTF fonts, the emergency console doesn't work without a font, which might be missing too
		mPages.push_back(mCurrentPage);
	}
}

int PageSet::LoadLanguage(char* languageFile, ZipArchiveHandle package)
{
	xml_document<> lang;
	xml_node<>* parent;
	xml_node<>* child;
	std::string resource_source;
	int ret = 0;

	if (languageFile) {
		printf("parsing languageFile\n");
		lang.parse<0>(languageFile);
		printf("parsing languageFile done\n");
	} else {
		return -1;
	}

	parent = lang.first_node("language");
	if (!parent) {
		LOGERR("Unable to locate language node in language file.\n");
		lang.clear();
		return -1;
	}

	child = parent->first_node("display");
	if (child) {
		DataManager::SetValue("tw_language_display", child->value());
		resource_source = child->value();
	} else {
		LOGERR("language file does not have a display value set\n");
		DataManager::SetValue("tw_language_display", "Not Set");
		resource_source = languageFile;
	}

	child = parent->first_node("resources");
	if (child)
		mResources->LoadResources(child, package, resource_source);
	else
		ret = -1;
	DataManager::SetValue("tw_backup_name", gui_lookup("auto_generate", "(Auto Generate)"));
	lang.clear();
	return ret;
}

int PageSet::LoadDetails(LoadingContext& ctx, xml_node<>* root)
{
	xml_node<>* child = root->first_node("details");
	if (child) {
		int theme_ver = 0;
		xml_node<>* themeversion = child->first_node("themeversion");
		if (themeversion && themeversion->value()) {
			theme_ver = atoi(themeversion->value());
		} else {
			LOGINFO("No themeversion in theme.\n");
		}
		if (theme_ver != TW_THEME_VERSION) {
			LOGINFO("theme version from xml: %i, expected %i\n", theme_ver, TW_THEME_VERSION);
			if (ctx.zip) {
				gui_err("theme_ver_err=Custom theme version does not match TWRP version. Using stock theme.");
				return TW_THEME_VER_ERR;
			} else {
				gui_print_color("warning", "Stock theme version does not match TWRP version.\n");
			}
		}
		xml_node<>* resolution = child->first_node("resolution");
		if (resolution) {
			LOGINFO("Checking resolution...\n");
			xml_attribute<>* width_attr = resolution->first_attribute("width");
			xml_attribute<>* height_attr = resolution->first_attribute("height");
			xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling");
			if (width_attr && height_attr && !noscale_attr) {
				int width = atoi(width_attr->value());
				int height = atoi(height_attr->value());
				int offx = 0, offy = 0;
#ifdef TW_ROUND_SCREEN
				xml_node<>* roundscreen = child->first_node("roundscreen");
				if (roundscreen) {
					LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n");
					xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x");
					xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y");
					if (offx_attr) {
						offx = atoi(offx_attr->value());
					}
					if (offy_attr) {
						offy = atoi(offy_attr->value());
					}
				}
#endif
				if (width != 0 && height != 0) {
					float scale_w = (((float)gr_fb_width() + (float)tw_w_offset) - ((float)offx * 2.0)) / (float)width;
					float scale_h = (((float)gr_fb_height() + (float)tw_h_offset) - ((float)offy * 2.0)) / (float)height;
#ifdef TW_ROUND_SCREEN
					float scale_off_w = ((float)gr_fb_width() + (float)tw_w_offset) / (float)width;
					float scale_off_h = ((float)gr_fb_height() + (float)tw_h_offset) / (float)height;
					tw_x_offset = offx * scale_off_w;
					tw_y_offset = offy * scale_off_h;
#endif
					if (scale_w != 1 || scale_h != 1) {
						LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i w: %i h: %i\n",
							scale_w, scale_h, tw_x_offset, tw_y_offset, tw_w_offset, tw_h_offset);
						set_scale_values(scale_w, scale_h);
					}
				}
			} else {
				LOGINFO("XML does not contain width and height, no scaling will be applied\n");
			}
		} else {
			LOGINFO("XML contains no resolution tag, no scaling will be applied.\n");
		}
	} else {
		LOGINFO("XML contains no details tag, no scaling will be applied.\n");
	}

	return 0;
}

int PageSet::SetPage(std::string page)
{
	Page* tmp = FindPage(page);
	if (tmp)
	{
		if (mCurrentPage)   mCurrentPage->SetPageFocus(0);
		mCurrentPage = tmp;
		mCurrentPage->SetPageFocus(1);
		mCurrentPage->NotifyVarChange("", "");
		return 0;
	}
	else
	{
		LOGERR("Unable to locate page (%s)\n", page.c_str());
	}
	return -1;
}

int PageSet::SetOverlay(Page* page)
{
	if (page) {
		if (mOverlays.size() >= 10) {
			LOGERR("Too many overlays requested, max is 10.\n");
			return -1;
		}

		std::vector<Page*>::iterator iter;
		for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
			if ((*iter)->GetName() == page->GetName()) {
				mOverlays.erase(iter);
				// SetOverlay() is (and should stay) the only function which
				// adds to mOverlays. Then, each page can appear at most once.
				break;
			}
		}

		page->SetPageFocus(1);
		page->NotifyVarChange("", "");

		if (!mOverlays.empty())
			mOverlays.back()->SetPageFocus(0);

		mOverlays.push_back(page);
	} else {
		if (!mOverlays.empty()) {
			mOverlays.back()->SetPageFocus(0);
			mOverlays.pop_back();
			if (!mOverlays.empty())
				mOverlays.back()->SetPageFocus(1);
			else if (mCurrentPage)
				mCurrentPage->SetPageFocus(1); // Just in case somehow the regular page lost focus, we'll set it again
		}
	}
	return 0;
}

const ResourceManager* PageSet::GetResources()
{
	return mResources;
}

Page* PageSet::FindPage(std::string name)
{
	std::vector<Page*>::iterator iter;

	for (iter = mPages.begin(); iter != mPages.end(); iter++)
	{
		if (name == (*iter)->GetName())
			return (*iter);
	}
	return NULL;
}

int PageSet::LoadVariables(xml_node<>* vars)
{
	xml_node<>* child;
	xml_attribute<> *name, *value, *persist;
	int p;

	child = vars->first_node("variable");
	while (child)
	{
		name = child->first_attribute("name");
		value = child->first_attribute("value");
		persist = child->first_attribute("persist");
		if (name && value)
		{
			if (strcmp(name->value(), "tw_x_offset") == 0) {
				tw_x_offset = atoi(value->value());
				child = child->next_sibling("variable");
				continue;
			}
			if (strcmp(name->value(), "tw_y_offset") == 0) {
				tw_y_offset = atoi(value->value());
				child = child->next_sibling("variable");
				continue;
			}
			if (strcmp(name->value(), "tw_w_offset") == 0) {
				tw_w_offset = atoi(value->value());
				child = child->next_sibling("variable");
				continue;
			}
			if (strcmp(name->value(), "tw_h_offset") == 0) {
				tw_h_offset = atoi(value->value());
				child = child->next_sibling("variable");
				continue;
			}
			p = persist ? atoi(persist->value()) : 0;
			string temp = value->value();
			string valstr = gui_parse_text(temp);

			if (valstr.find("+") != string::npos) {
				string val1str = valstr;
				val1str = val1str.substr(0, val1str.find('+'));
				string val2str = valstr;
				val2str = val2str.substr(val2str.find('+') + 1, string::npos);
				int val1 = atoi(val1str.c_str());
				int val2 = atoi(val2str.c_str());
				int val = val1 + val2;

				DataManager::SetValue(name->value(), val, p);
			} else if (valstr.find("-") != string::npos) {
				string val1str = valstr;
				val1str = val1str.substr(0, val1str.find('-'));
				string val2str = valstr;
				val2str = val2str.substr(val2str.find('-') + 1, string::npos);
				int val1 = atoi(val1str.c_str());
				int val2 = atoi(val2str.c_str());
				int val = val1 - val2;

				DataManager::SetValue(name->value(), val, p);
			} else {
				DataManager::SetValue(name->value(), valstr, p);
			}
		}

		child = child->next_sibling("variable");
	}
	return 0;
}

int PageSet::LoadPages(LoadingContext& ctx, xml_node<>* pages)
{
	xml_node<>* child;

	if (!pages)
		return -1;

	child = pages->first_node("page");
	while (child != NULL)
	{
		Page* page = new Page(child, &ctx.templates);
		if (page->GetName().empty())
		{
			LOGERR("Unable to process load page\n");
			delete page;
		}
		else
		{
			mPages.push_back(page);
		}
		child = child->next_sibling("page");
	}
	if (mPages.size() > 0)
		return 0;
	return -1;
}

int PageSet::IsCurrentPage(Page* page)
{
	return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
}

std::string PageSet::GetCurrentPage() const
{
	return mCurrentPage ? mCurrentPage->GetName() : "";
}

int PageSet::Render(void)
{
	int ret;

	ret = (mCurrentPage ? mCurrentPage->Render() : -1);
	if (ret < 0)
		return ret;

	std::vector<Page*>::iterator iter;

	for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
		ret = ((*iter) ? (*iter)->Render() : -1);
		if (ret < 0)
			return ret;
	}
	return ret;
}

int PageSet::Update(void)
{
	int ret;

	ret = (mCurrentPage ? mCurrentPage->Update() : -1);
	if (ret < 0 || ret > 1)
		return ret;

	std::vector<Page*>::iterator iter;

	for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
		ret = ((*iter) ? (*iter)->Update() : -1);
		if (ret < 0)
			return ret;
	}
	return ret;
}

int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	if (!mOverlays.empty())
		return mOverlays.back()->NotifyTouch(state, x, y);

	return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
}

int PageSet::NotifyKey(int key, bool down)
{
	if (!mOverlays.empty())
		return mOverlays.back()->NotifyKey(key, down);

	return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
}

int PageSet::NotifyCharInput(int ch)
{
	if (!mOverlays.empty())
		return mOverlays.back()->NotifyCharInput(ch);

	return (mCurrentPage ? mCurrentPage->NotifyCharInput(ch) : -1);
}

int PageSet::SetKeyBoardFocus(int inFocus)
{
	if (!mOverlays.empty())
		return mOverlays.back()->SetKeyBoardFocus(inFocus);

	return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
}

int PageSet::NotifyVarChange(std::string varName, std::string value)
{
	std::vector<Page*>::iterator iter;

	for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++)
		(*iter)->NotifyVarChange(varName, value);

	return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
}

void PageSet::AddStringResource(std::string resource_source, std::string resource_name, std::string value)
{
	mResources->AddStringResource(resource_source, resource_name, value);
}

char* PageManager::LoadFileToBuffer(std::string filename, ZipArchiveHandle package) {
	size_t len;
	char* buffer = NULL;

	if (package) {
		// We can try to load the XML directly...
		LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' directly\n", filename.c_str());
		struct stat st;
		if (stat(filename.c_str(),&st) != 0) {
			// This isn't always an error, sometimes we request files that don't exist.
			return NULL;
		}

		len = (size_t)st.st_size;

		buffer = (char*) malloc(len + 1);
		if (!buffer) {
			LOGERR("PageManager::LoadFileToBuffer failed to malloc\n");
			return NULL;
		}

		int fd = open(filename.c_str(), O_RDONLY);
		if (fd == -1) {
			LOGERR("PageManager::LoadFileToBuffer failed to open '%s' - (%s)\n", filename.c_str(), strerror(errno));
			free(buffer);
			return NULL;
		}

		if (read(fd, buffer, len) < 0) {
			LOGERR("PageManager::LoadFileToBuffer failed to read '%s' - (%s)\n", filename.c_str(), strerror(errno));
			free(buffer);
			close(fd);
			return NULL;
		}
		close(fd);
	} else {
		LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' from zip\n", filename.c_str());
		ZipEntry binary_entry;
		if (FindEntry(package, filename, &binary_entry) == 0) {
		// if (!package->EntryExists(filename)) {
			LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
			return NULL;
		}

		// Allocate the buffer for the file
		len = binary_entry.uncompressed_length;
		// len = package->GetUncompressedSize(filename);
		buffer = (char*) malloc(len + 1);
		if (!buffer)
			return NULL;

		int32_t err =
			ExtractToMemory(package, &binary_entry, reinterpret_cast<uint8_t*>(buffer), len);
		if (err != 0) {
		// if (!package->ExtractToBuffer(filename, (unsigned char*) buffer)) {
			LOGERR("Unable to extract '%s'\n", filename.c_str());
			free(buffer);
			return NULL;
		}
	}
	// NULL-terminate the string
	buffer[len] = 0x00;
	return buffer;
}

void PageManager::LoadLanguageListDir(string dir) {
	if (!TWFunc::Path_Exists(dir)) {
		LOGERR("LoadLanguageListDir '%s' path not found\n", dir.c_str());
		return;
	}

	DIR *d = opendir(dir.c_str());
	struct dirent *p;

	if (d == NULL) {
		LOGERR("LoadLanguageListDir error opening dir: '%s', %s\n", dir.c_str(), strerror(errno));
		return;
	}

	while ((p = readdir(d))) {
		if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..") || strlen(p->d_name) < 5)
			continue;

		string file = p->d_name;
		if (file.substr(strlen(p->d_name) - 4) != ".xml")
			continue;
		string path = dir + p->d_name;
		string file_no_extn = file.substr(0, strlen(p->d_name) - 4);
		struct language_struct language_entry;
		language_entry.filename = file_no_extn;
		char* xmlFile = PageManager::LoadFileToBuffer(dir + p->d_name, NULL);
		if (xmlFile == NULL) {
			LOGERR("LoadLanguageListDir unable to load '%s'\n", language_entry.filename.c_str());
			continue;
		}
		xml_document<> *doc = new xml_document<>();
		doc->parse<0>(xmlFile);

		xml_node<>* parent = doc->first_node("language");
		if (!parent) {
			LOGERR("Invalid language XML file '%s'\n", language_entry.filename.c_str());
		} else {
			xml_node<>* child = parent->first_node("display");
			if (child) {
				language_entry.displayvalue = child->value();
			} else {
				LOGERR("No display value for '%s'\n", language_entry.filename.c_str());
				language_entry.displayvalue = language_entry.filename;
			}
			Language_List.push_back(language_entry);
		}
		doc->clear();
		delete doc;
		free(xmlFile);
	}
	closedir(d);
}

void PageManager::LoadLanguageList(ZipArchiveHandle package) {
	Language_List.clear();
	if (TWFunc::Path_Exists(TWRES "customlanguages"))
		TWFunc::removeDir(TWRES "customlanguages", true);
	if (package) {
		TWFunc::Recursive_Mkdir(TWRES "customlanguages");
		ExtractPackageRecursive(package, "", TWRES "customlanguages", nullptr, nullptr);

		// package->ExtractRecursive("languages", TWRES "customlanguages/");
		LoadLanguageListDir(TWRES "customlanguages/");
	} else {
		LoadLanguageListDir(TWRES "languages/");
	}

	std::sort(Language_List.begin(), Language_List.end());
}

void PageManager::LoadLanguage(string filename) {
	string actual_filename;
	if (TWFunc::Path_Exists(TWRES "customlanguages/" + filename + ".xml"))
		actual_filename = TWRES "customlanguages/" + filename + ".xml";
	else
		actual_filename = TWRES "languages/" + filename + ".xml";
	char* xmlFile = PageManager::LoadFileToBuffer(actual_filename, NULL);
	if (xmlFile == NULL)
		LOGERR("Unable to load '%s'\n", actual_filename.c_str());
	else {
		mCurrentSet->LoadLanguage(xmlFile, NULL);
		free(xmlFile);
	}
	PartitionManager.Translate_Partition_Display_Names();
}

int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
{
	std::string mainxmlfilename = package;
	char* languageFile = NULL;
	char* baseLanguageFile = NULL;
	PageSet* pageSet = NULL;
	int ret;

	mReloadTheme = false;
	mStartPage = startpage;

	// init the loading context
	LoadingContext ctx;

	// Open the XML file
	LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
	if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
	{
		LOGINFO("Load XML directly\n");
		tw_x_offset = TW_X_OFFSET;
		tw_y_offset = TW_Y_OFFSET;
		tw_w_offset = TW_W_OFFSET;
		tw_h_offset = TW_H_OFFSET;
		if (name != "splash") {
			LoadLanguageList(NULL);
			languageFile = LoadFileToBuffer(TWRES "languages/en.xml", NULL);
		}
		ctx.basepath = TWRES;
	}
	else
	{
		LOGINFO("Loading zip theme\n");
		tw_x_offset = 0;
		tw_y_offset = 0;
		tw_w_offset = 0;
		tw_h_offset = 0;
		if (!TWFunc::Path_Exists(package))
			return -1;

		ZipArchiveHandle Zip;
		int err = OpenArchive(package.c_str(), &Zip);

		if (err != 0)
			return -1;
		
		ctx.zip = Zip;
		mainxmlfilename = "ui.xml";
		LoadLanguageList(ctx.zip);
		languageFile = LoadFileToBuffer("languages/en.xml", ctx.zip);
		baseLanguageFile = LoadFileToBuffer(TWRES "languages/en.xml", NULL);
	}

	// Before loading, mCurrentSet must be the loading package so we can find resources
	pageSet = mCurrentSet;
	mCurrentSet = new PageSet();

	if (baseLanguageFile) {
		mCurrentSet->LoadLanguage(baseLanguageFile, NULL);
		free(baseLanguageFile);
	}

	if (languageFile) {
		mCurrentSet->LoadLanguage(languageFile, ctx.zip);
		free(languageFile);
	}

	// Load and parse the XML and all includes
	currentLoadingContext = &ctx; // required to find styles
	ret = mCurrentSet->Load(ctx, mainxmlfilename);
	currentLoadingContext = NULL;

	if (ret == 0) {
		mCurrentSet->SetPage(startpage);
		mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
	} else {
		if (ret != TW_THEME_VER_ERR)
			LOGERR("Package %s failed to load.\n", name.c_str());
	}

	// reset to previous pageset
	mCurrentSet = pageSet;

	if (ctx.zip) {
		CloseArchive(ctx.zip);
	}
	return ret;
}

PageSet* PageManager::FindPackage(std::string name)
{
	std::map<std::string, PageSet*>::iterator iter;

	iter = mPageSets.find(name);
	if (iter != mPageSets.end())
		return (*iter).second;

	LOGERR("Unable to locate package %s\n", name.c_str());
	return NULL;
}

PageSet* PageManager::SelectPackage(std::string name)
{
	LOGINFO("Switching packages (%s)\n", name.c_str());
	PageSet* tmp;

	tmp = FindPackage(name);
	if (tmp)
	{
		mCurrentSet = tmp;
		mCurrentSet->MakeEmergencyConsoleIfNeeded();
		mCurrentSet->NotifyVarChange("", "");
	}
	else
		LOGERR("Unable to find package.\n");

	return mCurrentSet;
}

int PageManager::ReloadPackage(std::string name, std::string package)
{
	std::map<std::string, PageSet*>::iterator iter;

	mReloadTheme = false;

	iter = mPageSets.find(name);
	if (iter == mPageSets.end())
		return -1;

	if (mMouseCursor)
		mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());

	PageSet* set = (*iter).second;
	mPageSets.erase(iter);

	if (LoadPackage(name, package, mStartPage) != 0)
	{
		LOGINFO("Failed to load package '%s'.\n", package.c_str());
		mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
		return -1;
	}
	if (mCurrentSet == set)
		SelectPackage(name);
	delete set;
	GUIConsole::Translate_Now();
	return 0;
}

void PageManager::ReleasePackage(std::string name)
{
	std::map<std::string, PageSet*>::iterator iter;

	iter = mPageSets.find(name);
	if (iter == mPageSets.end())
		return;

	PageSet* set = (*iter).second;
	mPageSets.erase(iter);
	delete set;
	if (set == mCurrentSet)
		mCurrentSet = NULL;
	return;
}

int PageManager::RunReload() {
	int ret_val = 0;
	std::string theme_path;

	if (!mReloadTheme)
		return 0;

	mReloadTheme = false;
	theme_path = DataManager::GetSettingsStoragePath();
	if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
		LOGERR("Unable to mount %s during gui_reload_theme function.\n", theme_path.c_str());
		ret_val = 1;
	}

	theme_path += "/TWRP/theme/ui.zip";
	if (ret_val != 0 || ReloadPackage("TWRP", theme_path) != 0)
	{
		// Loading the custom theme failed - try loading the stock theme
		LOGINFO("Attempting to reload stock theme...\n");
		if (ReloadPackage("TWRP", TWRES "ui.xml"))
		{
			LOGERR("Failed to load base packages.\n");
			ret_val = 1;
		}
	}
	if (ret_val == 0) {
		if (DataManager::GetStrValue("tw_language") != "en.xml") {
			LOGINFO("Loading language '%s'\n", DataManager::GetStrValue("tw_language").c_str());
			LoadLanguage(DataManager::GetStrValue("tw_language"));
		}
	}

	// This makes the console re-translate
	GUIConsole::Clear_For_Retranslation();

	return ret_val;
}

void PageManager::RequestReload() {
	mReloadTheme = true;
}

void PageManager::SetStartPage(const std::string& page_name) {
	mStartPage = page_name;
}

int PageManager::ChangePage(std::string name)
{
	DataManager::SetValue("tw_operation_state", 0);
	int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
	return ret;
}

std::string PageManager::GetCurrentPage()
{
	return mCurrentSet ? mCurrentSet->GetCurrentPage() : "";
}

int PageManager::ChangeOverlay(std::string name)
{
	if (name.empty())
		return mCurrentSet->SetOverlay(NULL);
	else
	{
		Page* page = mCurrentSet ? mCurrentSet->FindPage(name) : NULL;
		return mCurrentSet->SetOverlay(page);
	}
}

const ResourceManager* PageManager::GetResources()
{
	return (mCurrentSet ? mCurrentSet->GetResources() : NULL);
}

int PageManager::IsCurrentPage(Page* page)
{
	return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
}

int PageManager::Render(void)
{
	if (blankTimer.isScreenOff())
		return 0;

	int res = (mCurrentSet ? mCurrentSet->Render() : -1);
	if (mMouseCursor)
		mMouseCursor->Render();
	return res;
}

HardwareKeyboard *PageManager::GetHardwareKeyboard()
{
	if (!mHardwareKeyboard)
		mHardwareKeyboard = new HardwareKeyboard();
	return mHardwareKeyboard;
}

xml_node<>* PageManager::FindStyle(std::string name)
{
	if (!currentLoadingContext)
	{
		LOGERR("FindStyle works only while loading a theme.\n");
		return NULL;
	}

	for (std::vector<xml_node<>*>::iterator itr = currentLoadingContext->styles.begin(); itr != currentLoadingContext->styles.end(); itr++) {
		xml_node<>* node = (*itr)->first_node("style");

		while (node) {
			if (!node->first_attribute("name"))
				continue;

			if (name == node->first_attribute("name")->value())
				return node;
			node = node->next_sibling("style");
		}
	}
	return NULL;
}

MouseCursor *PageManager::GetMouseCursor()
{
	if (!mMouseCursor)
		mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
	return mMouseCursor;
}

void PageManager::LoadCursorData(xml_node<>* node)
{
	if (!mMouseCursor)
		mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());

	mMouseCursor->LoadData(node);
}

int PageManager::Update(void)
{
	if (blankTimer.isScreenOff())
		return 0;

	if (RunReload())
		return -2;

	int res = (mCurrentSet ? mCurrentSet->Update() : -1);

	if (mMouseCursor)
	{
		int c_res = mMouseCursor->Update();
		if (c_res > res)
			res = c_res;
	}
	return res;
}

int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
}

int PageManager::NotifyKey(int key, bool down)
{
	return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
}

int PageManager::NotifyCharInput(int ch)
{
	return (mCurrentSet ? mCurrentSet->NotifyCharInput(ch) : -1);
}

int PageManager::SetKeyBoardFocus(int inFocus)
{
	return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
}

int PageManager::NotifyVarChange(std::string varName, std::string value)
{
	return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
}

void PageManager::AddStringResource(std::string resource_source, std::string resource_name, std::string value)
{
	if (mCurrentSet)
		mCurrentSet->AddStringResource(resource_source, resource_name, value);
}

extern "C" void gui_notifyVarChange(const char *name, const char* value)
{
	if (!gGuiRunning)
		return;

	PageManager::NotifyVarChange(name, value);
}
