/*
        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 <linux/input.h>
#include <stdlib.h>
#include <string.h>
#include "../data.hpp"

#include <string>

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

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

bool GUIKeyboard::CtrlActive = false;

GUIKeyboard::GUIKeyboard(xml_node<>* node)
	: GUIObject(node)
{
	int layoutindex, rowindex, keyindex, Xindex, Yindex, keyHeight = 0, keyWidth = 0;
	currentKey = NULL;
	highlightRenderCount = 0;
	hasHighlight = hasCapsHighlight = hasCtrlHighlight = false;
	char resource[10], layout[8], row[5], key[6], longpress[7];
	xml_attribute<>* attr;
	xml_node<>* child;
	xml_node<>* keylayout;
	xml_node<>* keyrow;

	for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++) {
		layouts[layoutindex].keyboardImg = NULL;
		memset(layouts[layoutindex].keys, 0, sizeof(Layout::keys));
		memset(layouts[layoutindex].row_end_y, 0, sizeof(Layout::row_end_y));
	}

	mRendered = false;
	currentLayout = 1;
	CapsLockOn = false;

	if (!node)  return;

	mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
	mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
	mCtrlHighlightColor = LoadAttrColor(FindNode(node, "ctrlhighlight"), "color", &hasCtrlHighlight);

	child = FindNode(node, "keymargin");
	mKeyMarginX = LoadAttrIntScaleX(child, "x", 0);
	mKeyMarginY = LoadAttrIntScaleY(child, "y", 0);

	child = FindNode(node, "background");
	mBackgroundColor = LoadAttrColor(child, "color", COLOR(32,32,32,255));

	child = FindNode(node, "key-alphanumeric");
	mFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel"));
	mFontColor = LoadAttrColor(child, "textcolor", COLOR(255,255,255,255));
	mKeyColorAlphanumeric = LoadAttrColor(child, "color", COLOR(0,0,0,0));

	child = FindNode(node, "key-other");
	mSmallFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-small"));
	mFontColorSmall = LoadAttrColor(child, "textcolor", COLOR(192,192,192,255));
	mKeyColorOther = LoadAttrColor(child, "color", COLOR(0,0,0,0));

	child = FindNode(node, "longpress");
	mLongpressFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-longpress"));
	mLongpressFontColor = LoadAttrColor(child, "textcolor", COLOR(128,128,128,255));
	LoadPlacement(child, &longpressOffsetX, &longpressOffsetY);

	LoadKeyLabels(node, 0); // load global key labels

	// compatibility ugliness: resources should be specified in the layouts themselves instead
	// Load the images for the different layouts
	child = FindNode(node, "layout");
	if (child)
	{
		layoutindex = 1;
		strcpy(resource, "resource1");
		attr = child->first_attribute(resource);
		while (attr && layoutindex < (MAX_KEYBOARD_LAYOUTS + 1)) {
			layouts[layoutindex - 1].keyboardImg = LoadAttrImage(child, resource);

			layoutindex++;
			resource[8] = (char)(layoutindex + 48);
			attr = child->first_attribute(resource);
		}
	}

	// Check the first image to get height and width
	if (layouts[0].keyboardImg && layouts[0].keyboardImg->GetResource())
	{
		mRenderW = layouts[0].keyboardImg->GetWidth();
		mRenderH = layouts[0].keyboardImg->GetHeight();
	}

	// Load all of the layout maps
	layoutindex = 1;
	strcpy(layout, "layout1");
	keylayout = FindNode(node, layout);
	while (keylayout)
	{
		if (layoutindex > MAX_KEYBOARD_LAYOUTS) {
			LOGERR("Too many layouts defined in keyboard.\n");
			return;
		}

		LoadKeyLabels(keylayout, layoutindex); // load per-layout key labels

		Layout& lay = layouts[layoutindex - 1];

		child = keylayout->first_node("keysize");
		keyHeight = LoadAttrIntScaleY(child, "height", 0);
		keyWidth = LoadAttrIntScaleX(child, "width", 0);
		// compatibility ugliness: capslock="0" means that this is the caps layout. Also it has nothing to do with keysize.
		lay.is_caps = (LoadAttrInt(child, "capslock", 1) == 0);
		// compatibility ugliness: revert_layout has nothing to do with keysize.
		lay.revert_layout = LoadAttrInt(child, "revert_layout", -1);

		rowindex = 1;
		Yindex = 0;
		strcpy(row, "row1");
		keyrow = keylayout->first_node(row);
		while (keyrow)
		{
			if (rowindex > MAX_KEYBOARD_ROWS) {
				LOGERR("Too many rows defined in keyboard.\n");
				return;
			}

			Yindex += keyHeight;
			lay.row_end_y[rowindex - 1] = Yindex;

			keyindex = 1;
			Xindex = 0;
			strcpy(key, "key01");
			attr = keyrow->first_attribute(key);

			while (attr) {
				if (keyindex > MAX_KEYBOARD_KEYS) {
					LOGERR("Too many keys defined in a keyboard row.\n");
					return;
				}

				const char* keyinfo = attr->value();

				if (strlen(keyinfo) == 0) {
					LOGERR("No key info on layout%i, row%i, key%dd.\n", layoutindex, rowindex, keyindex);
					return;
				}

				if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
					LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);


				// PROCESS LONG PRESS INFO IF EXISTS
				sprintf(longpress, "long%02i", keyindex);
				attr = keyrow->first_attribute(longpress);
				if (attr) {
					const char* keyinfo = attr->value();

					if (strlen(keyinfo) == 0) {
						LOGERR("No long press info on layout%i, row%i, long%dd.\n", layoutindex, rowindex, keyindex);
						return;
					}

					if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
						LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
				}
				keyindex++;
				sprintf(key, "key%02i", keyindex);
				attr = keyrow->first_attribute(key);
			}
			rowindex++;
			row[3] = (char)(rowindex + 48);
			keyrow = keylayout->first_node(row);
		}
		layoutindex++;
		layout[6] = (char)(layoutindex + 48);
		keylayout = FindNode(node, layout);
	}

	int x, y;
	// Load the placement
	LoadPlacement(FindNode(node, "placement"), &x, &y, &mRenderW, &mRenderH);
	SetRenderPos(x, y, mRenderW, mRenderH);
	return;
}

GUIKeyboard::~GUIKeyboard()
{
}

int GUIKeyboard::ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress)
{
	key.layout = 0;
	int keychar = 0;
	if (strlen(keyinfo) == 1) {
		// This is a single key, simple definition
		keychar = keyinfo[0];
	} else {
		// This key has extra data: {keywidth}:{what_the_key_does}
		keyWidth = scale_theme_x(atoi(keyinfo));

		const char* ptr = keyinfo;
		while (*ptr > 32 && *ptr != ':')
			ptr++;
		if (*ptr != ':')
			return -1;  // no colon is an error
		ptr++;

		if (*ptr == 0) {  // This is an empty area
			keychar = 0;
		} else if (strlen(ptr) == 1) {  // This is the character that this key uses
			keychar = *ptr;
		} else if (*ptr == 'c') {  // This is an ASCII character code: "c:{number}"
			keychar = atoi(ptr + 2);
		} else if (*ptr == 'k') {  // This is a Linux keycode from input.h: "k:{number}"
			keychar = -atoi(ptr + 2);
		} else if (*ptr == 'l') {  // This is a different layout: "layout{number}"
			key.layout = atoi(ptr + 6);
		} else if (*ptr == 'a') {  // This is an action: "action" (the Enter key)
			keychar = KEYBOARD_ACTION;
		} else
			return -1;
	}

	if (longpress) {
		key.longpresskey = keychar;
	} else {
		key.key = keychar;
		Xindex += keyWidth;
		key.end_x = Xindex - 1;
	}

	return 0;
}

void GUIKeyboard::LoadKeyLabels(xml_node<>* parent, int layout)
{
	for (xml_node<>* child = parent->first_node(); child; child = child->next_sibling()) {
		std::string name = child->name();
		if (name == "keylabel") {
			std::string keydef = LoadAttrString(child, "key", "");
			Key tempkey;
			int dummyX;
			if (ParseKey(keydef.c_str(), tempkey, dummyX, 0, false) == 0) {
				KeyLabel keylabel;
				keylabel.key = tempkey.key;
				keylabel.layout_from = layout;
				keylabel.layout_to = tempkey.layout;
				keylabel.text = LoadAttrString(child, "text", "");
				keylabel.image = LoadAttrImage(child, "resource");
				mKeyLabels.push_back(keylabel);
			} else {
				LOGERR("Ignoring invalid keylabel in layout %d: '%s'.\n", layout, keydef.c_str());
			}
		}
	}
}

void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
{
	int keychar = key.key;
	if (!keychar && !key.layout)
		return;

	// key background
	COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther;
	gr_color(c.red, c.green, c.blue, c.alpha);
	keyX += mKeyMarginX;
	keyY += mKeyMarginY;
	keyW -= mKeyMarginX * 2;
	keyH -= mKeyMarginY * 2;
	gr_fill(keyX, keyY, keyW, keyH);

	// key label
	FontResource* labelFont = mFont;
	string labelText;
	ImageResource* labelImage = NULL;
	if (keychar > 32 && keychar < 127) {
		// TODO: this will eventually need UTF-8 support
		labelText = (char) keychar;
		if (CtrlActive) {
			int ctrlchar = KeyCharToCtrlChar(keychar);
			if (ctrlchar != keychar)
				labelText = std::string("^") + (char)(ctrlchar + 64);
		}
		gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
	}
	else {
		// search for a special key label
		for (std::vector<KeyLabel>::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) {
			if (it->layout_from > 0 && it->layout_from != currentLayout)
				continue; // this label is for another layout
			if (it->key == key.key && it->layout_to == key.layout)
			{
				// found a label
				labelText = it->text;
				labelImage = it->image;
				break;
			}
		}
		labelFont = mSmallFont;
		gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha);
	}

	if (labelImage && labelImage->GetResource())
	{
		int w = labelImage->GetWidth();
		int h = labelImage->GetHeight();
		int x = keyX + (keyW - w) / 2;
		int y = keyY + (keyH - h) / 2;
		gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y);
	}
	else if (!labelText.empty() && labelFont && labelFont->GetResource())
	{
		void* fontResource = labelFont->GetResource();
		int textW = gr_ttf_measureEx(labelText.c_str(), fontResource);
		int textH = labelFont->GetHeight();
		int textX = keyX + (keyW - textW) / 2;
		int textY = keyY + (keyH - textH) / 2;
		gr_textEx_scaleW(textX, textY, labelText.c_str(), fontResource, keyW, TOP_LEFT, 0);
	}

	// longpress key label (only if font is defined)
	keychar = key.longpresskey;
	if (keychar > 32 && keychar < 127 && mLongpressFont && mLongpressFont->GetResource()) {
		void* fontResource = mLongpressFont->GetResource();
		gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha);
		string text(1, keychar);
		int textW = gr_ttf_measureEx(text.c_str(), fontResource);
		int textX = keyX + keyW - longpressOffsetX - textW;
		int textY = keyY + longpressOffsetY;
		gr_textEx_scaleW(textX, textY, text.c_str(), fontResource, keyW, TOP_LEFT, 0);
	}
}

int GUIKeyboard::KeyCharToCtrlChar(int key)
{
	// convert upper and lower case to ctrl chars
	// Ctrl+A to Ctrl+_ (we don't support entering null bytes)
	if (key >= 65 && key <= 127 && key != 96)
		return key & 0x1f;
	return key; // pass on others (already ctrl chars, numbers, etc.) unchanged
}

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

	Layout& lay = layouts[currentLayout - 1];

	bool drawKeys = false;
	if (lay.keyboardImg && lay.keyboardImg->GetResource())
		// keyboard is image based
		gr_blit(lay.keyboardImg->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
	else {
		// keyboard is software drawn
		// fill background
		gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha);
		gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
		drawKeys = true;
	}

	// draw keys
	int y1 = 0;
	for (int row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
		int rowY = mRenderY + y1;
		int rowH = lay.row_end_y[row] - y1;
		y1 = lay.row_end_y[row];
		int x1 = 0;
		for (int col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
			Key& key = lay.keys[row][col];
			int keyY = rowY;
			int keyH = rowH;
			int keyX = mRenderX + x1;
			int keyW = key.end_x - x1;
			x1 = key.end_x;

			// Draw key for software drawn keyboard
			if (drawKeys)
				DrawKey(key, keyX, keyY, keyW, keyH);

			// Draw highlight for capslock
			if (hasCapsHighlight && lay.is_caps && CapsLockOn && key.layout > 0 && key.layout == lay.revert_layout) {
				gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha);
				gr_fill(keyX, keyY, keyW, keyH);
			}

			// Draw highlight for control
			if (hasCtrlHighlight && key.key == -KEY_LEFTCTRL && CtrlActive) {
				gr_color(mCtrlHighlightColor.red, mCtrlHighlightColor.green, mCtrlHighlightColor.blue, mCtrlHighlightColor.alpha);
				gr_fill(keyX, keyY, keyW, keyH);
			}

			// Highlight current key
			if (hasHighlight && &key == currentKey && highlightRenderCount != 0) {
				gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
				gr_fill(keyX, keyY, keyW, keyH);
			}
		}
	}

	if (!hasHighlight || highlightRenderCount == 0)
		mRendered = true;
	else if (highlightRenderCount > 0)
		highlightRenderCount--;
	return 0;
}

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

	return 0;
}

int GUIKeyboard::SetRenderPos(int x, int y, int w, int h)
{
	RenderObject::SetRenderPos(x, y, w, h);
	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
	return 0;
}

GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
{
	if (!IsInRegion(x, y))
		return NULL;

	int rely = y - mRenderY;
	int relx = x - mRenderX;

	Layout& lay = layouts[currentLayout - 1];

	// Find the correct row
	int row;
	for (row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
		if (lay.row_end_y[row] > rely)
			break;
	}
	if (row == MAX_KEYBOARD_ROWS)
		return NULL;

	// Find the correct key (column)
	int col;
	int x1 = 0;
	for (col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
		Key& key = lay.keys[row][col];
		if (x1 <= relx && relx < key.end_x && (key.key != 0 || key.layout != 0)) {
			// This is the key that was pressed!
			return &key;
		}
		x1 = key.end_x;
	}
	return NULL;
}

int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	static int was_held = 0, startX = 0;

	if (!isConditionTrue())	 return -1;

	switch (state)
	{
	case TOUCH_START:
		was_held = 0;
		startX = x;
		currentKey = HitTestKey(x, y);
		if (currentKey)
			highlightRenderCount = -1;
		else
			highlightRenderCount = 0;
		mRendered = false;
		break;

	case TOUCH_DRAG:
		break;

	case TOUCH_RELEASE:
		// TODO: we might want to notify of key releases here
		if (x < startX - (mRenderW * 0.5)) {
			if (highlightRenderCount != 0) {
				highlightRenderCount = 0;
				mRendered = false;
			}
			PageManager::NotifyCharInput(KEYBOARD_SWIPE_LEFT);
			return 0;
		} else if (x > startX + (mRenderW * 0.5)) {
			if (highlightRenderCount != 0) {
				highlightRenderCount = 0;
				mRendered = false;
			}
			PageManager::NotifyCharInput(KEYBOARD_SWIPE_RIGHT);
			return 0;
		}
		// fall through
	case TOUCH_HOLD:
	case TOUCH_REPEAT:
		if (!currentKey) {
			if (highlightRenderCount != 0) {
				highlightRenderCount = 0;
				mRendered = false;
			}
			return 0;
		}

		if (highlightRenderCount != 0) {
			if (state == TOUCH_RELEASE)
				highlightRenderCount = 2;
			else
				highlightRenderCount = -1;
			mRendered = false;
		}

		if (HitTestKey(x, y) != currentKey) {
			// We dragged off of the starting key
			currentKey = NULL;
			if (highlightRenderCount != 0) {
				highlightRenderCount = 0;
				mRendered = false;
			}
			return 0;
		} else {
			Key& key = *currentKey;
			bool repeatKey = false;
			Layout& lay = layouts[currentLayout - 1];
			if (state == TOUCH_RELEASE && was_held == 0) {
				DataManager::Vibrate("tw_keyboard_vibrate");
				if (key.layout > 0) {
					// Switch layouts
					if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
						CapsLockOn = true; // Set the caps lock
					} else {
						CapsLockOn = false; // Unset the caps lock and change layouts
						currentLayout = key.layout;
					}
					mRendered = false;
				} else if (key.key == KEYBOARD_ACTION) {
					// Action
					highlightRenderCount = 0;
					// Send action notification
					PageManager::NotifyCharInput(key.key);
				} else if (key.key == -KEY_LEFTCTRL) {
					CtrlActive = !CtrlActive; // toggle Control key state
					mRendered = false; // render Ctrl key highlight
				} else if (key.key != 0) {
					// Regular key
					if (key.key > 0) {
						// ASCII code or character
						int keycode = key.key;
						if (CtrlActive) {
							CtrlActive = false;
							mRendered = false;
							keycode = KeyCharToCtrlChar(key.key);
						}
						PageManager::NotifyCharInput(keycode);
					} else {
						// Linux key code
						PageManager::NotifyKey(-key.key, true);
						PageManager::NotifyKey(-key.key, false);
					}
					if (!CapsLockOn && lay.is_caps) {
						// caps lock was not set, change layouts
						currentLayout = lay.revert_layout;
						mRendered = false;
					}
				}
			} else if (state == TOUCH_HOLD) {
				was_held = 1;
				if (key.longpresskey > 0) {
					// Long Press Key
					DataManager::Vibrate("tw_keyboard_vibrate");
					PageManager::NotifyCharInput(key.longpresskey);
				}
				else
					repeatKey = true;
			} else if (state == TOUCH_REPEAT) {
				was_held = 1;
				repeatKey = true;
			}
			if (repeatKey) {
				if (key.key == KEYBOARD_BACKSPACE) {
					// Repeat backspace
					PageManager::NotifyCharInput(key.key);
				}
				switch (key.key)
				{
					// Repeat arrows
					case -KEY_LEFT:
					case -KEY_RIGHT:
					case -KEY_UP:
					case -KEY_DOWN:
						PageManager::NotifyKey(-key.key, true);
						PageManager::NotifyKey(-key.key, false);
						break;
				}
			}
		}
		break;
	}

	return 0;
}

void GUIKeyboard::SetPageFocus(int inFocus)
{
	if (inFocus)
		CtrlActive = false;
}
