/*
        Copyright 2012 to 2016 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/>.
*/

// input.cpp - GUIInput object

#include <linux/input.h>
#include <pthread.h>
#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 <string>

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

#include "rapidxml.hpp"
#include "objects.hpp"
#include "../data.hpp"

#define TW_INPUT_NO_UPDATE -1000 // Magic value for HandleTextLocation when no change in scrolling has occurred

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

	mInputText = NULL;
	mAction = NULL;
	mBackground = NULL;
	mCursor = NULL;
	mFont = NULL;
	mRendered = false;
	HasMask = false;
	DrawCursor = false;
	isLocalChange = true;
	HasAllowed = false;
	HasDisabled = false;
	cursorX = textWidth = scrollingX = mFontHeight = mFontY = lastX = 0;
	mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
	mCursorLocation = -1; // -1 is always the end of the string
	CursorWidth = 3;
	ConvertStrToColor("black", &mBackgroundColor);
	ConvertStrToColor("white", &mCursorColor);
	mValue = "";
	displayValue = "";

	if (!node)
		return;

	// Load text directly from the node
	mInputText = new GUIText(node);
	// Load action directly from the node
	mAction = new GUIAction(node);

	if (mInputText->Render() < 0)
	{
		delete mInputText;
		mInputText = NULL;
	}

	// Load the background
	child = FindNode(node, "background");
	if (child)
	{
		mBackground = LoadAttrImage(child, "resource");
		mBackgroundColor = LoadAttrColor(child, "color", mBackgroundColor);
	}
	if (mBackground && mBackground->GetResource())
	{
		mBackgroundW = mBackground->GetWidth();
		mBackgroundH = mBackground->GetHeight();
	}

	// Load the cursor color
	child = FindNode(node, "cursor");
	if (child)
	{
		mCursor = LoadAttrImage(child, "resource");
		mCursorColor = LoadAttrColor(child, "color", mCursorColor);
		attr = child->first_attribute("hasfocus");
		if (attr)
		{
			std::string focus = attr->value();
			SetInputFocus(atoi(focus.c_str()));
		}
		CursorWidth = LoadAttrIntScaleX(child, "width", CursorWidth);
	}
	DrawCursor = HasInputFocus;

	// Load the font
	child = FindNode(node, "font");
	if (child)
	{
		mFont = LoadAttrFont(child, "resource");
		mFontHeight = mFont->GetHeight();
	}

	child = FindNode(node, "data");
	if (child)
	{
		attr = child->first_attribute("name");
		if (attr)
			mVariable = attr->value();
		attr = child->first_attribute("default");
		if (attr)
			DataManager::SetValue(mVariable, attr->value());
		mMask = LoadAttrString(child, "mask");
		HasMask = !mMask.empty();
	}

	// Load input restrictions
	child = FindNode(node, "restrict");
	if (child)
	{
		MinLen = LoadAttrInt(child, "minlen", MinLen);
		MaxLen = LoadAttrInt(child, "maxlen", MaxLen);
		AllowedList = LoadAttrString(child, "allow");
		HasAllowed = !AllowedList.empty();
		DisabledList = LoadAttrString(child, "disable");
		HasDisabled = !DisabledList.empty();
	}

	// Load the placement
	LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);

	if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
		mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
		mInputText->SetRenderPos(mRenderX, mFontY);
	} else
		mFontY = mRenderY;

	if (mInputText)
		mInputText->SetMaxWidth(0);
}

GUIInput::~GUIInput()
{
	delete mInputText;
	delete mAction;
}

void GUIInput::HandleTextLocation(int x) {
	mRendered = false;
	if (textWidth <= mRenderW) {
		if (x != TW_INPUT_NO_UPDATE)
			lastX = x;
		scrollingX = 0;
		return;
	}
	if (scrollingX + textWidth < mRenderW) {
		scrollingX = mRenderW - textWidth;
	}

	if (x == TW_INPUT_NO_UPDATE)
		return;

	scrollingX += x - lastX;
	if (scrollingX > 0)
		scrollingX = 0;
	else if (scrollingX + textWidth < mRenderW)
		scrollingX = mRenderW - textWidth;
	lastX = x;
}

void GUIInput::UpdateDisplayText() {
	void* fontResource = NULL;

	if (mFont) {
		fontResource = mFont->GetResource();
	} else {
		textWidth = 0;
		return;
	}

	DataManager::GetValue(mVariable, mValue);
	if (HasMask) {
		int index, string_size = mValue.size();
		string maskedValue;
		for (index=0; index<string_size; index++)
			maskedValue += mMask;
		displayValue = maskedValue;
	} else {
		displayValue = mValue;
	}

	textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
}

void GUIInput::HandleCursorByTouch(int x) {
// Uses x to find mCursorLocation and cursorX
	if (displayValue.size() == 0) {
		mCursorLocation = -1;
		cursorX = mRenderX;
		return;
	}

	void* fontResource = NULL;
	if (mFont) {
		fontResource = mFont->GetResource();
	} else {
		return;
	}

	string cursorString;
	unsigned index = 0, displaySize = displayValue.size();
	int prevX = mRenderX + scrollingX;

	for (index = 0; index <= displaySize; index++) {
		cursorString = displayValue.substr(0, index);
		cursorX = gr_ttf_measureEx(cursorString.c_str(), fontResource) + mRenderX + scrollingX;
		if (cursorX > x) {
			if (index > 0 && x <= cursorX - ((x - prevX) / 2) && prevX >= mRenderX) {
				// This helps make sure that we can place the cursor before the very first char if the first char is
				// is fully visible while also still letting us place the cursor after the last char if fully visible
				mCursorLocation = index - 1;
				cursorX = prevX;
				return;
			}
			mCursorLocation = index;
			if (cursorX > mRenderX + mRenderW) {
				cursorX = prevX; // This makes sure that the cursor doesn't get placed after the end of the input box
				mCursorLocation--;
				return;
			}
			if (cursorX >= mRenderX) {
				return; // This makes sure that the cursor doesn't get placed before the beginning of the input box
			}
		}
		prevX = cursorX;
	}
	mCursorLocation = -1; // x is at or past the end of the string
}

void GUIInput::HandleCursorByText() {
// Uses mCursorLocation to find cursorX
	if (!DrawCursor)
		return;

	void* fontResource = NULL;
	if (mFont) {
		fontResource = mFont->GetResource();
	} else {
		return;
	}

	int cursorTextWidth = textWidth; // width of text to the left of the cursor

	if (mCursorLocation != -1) {
		string cursorDisplay = displayValue;
		cursorDisplay.resize(mCursorLocation);
		cursorTextWidth = gr_ttf_measureEx(cursorDisplay.c_str(), fontResource);
	}
	cursorX = mRenderX + cursorTextWidth + scrollingX;
	if (cursorX >= mRenderX + mRenderW) {
		scrollingX = mRenderW - cursorTextWidth;
		cursorX = mRenderX + mRenderW - CursorWidth;
	} else if (cursorX < mRenderX) {
		scrollingX = cursorTextWidth * -1;
		cursorX = mRenderX;
	}
}

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

	void* fontResource = NULL;
	if (mFont)  fontResource = mFont->GetResource();

	// First step, fill background
	gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
	gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);

	// Next, render the background resource (if it exists)
	if (mBackground && mBackground->GetResource())
	{
		mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
		mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
		gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
	}

	int ret = 0;

	// Render the text
	if (mInputText) {
		mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
		mInputText->SetText(displayValue);
		gr_clip(mRenderX, mRenderY, mRenderW, mRenderH);
		ret = mInputText->Render();
		gr_noclip();
	}
	if (ret < 0)
		return ret;

	if (HasInputFocus && DrawCursor) {
		// Render the cursor
		gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
		gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
	}

	mRendered = true;
	return ret;
}

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

	int ret = 0;

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

	return ret;
}

int GUIInput::GetSelection(int x, int y)
{
	if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
	return (x - mRenderX);
}

int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
{
	static int startSelection = -1;
	void* fontResource = NULL;

	if (mFont)  fontResource = mFont->GetResource();

	if (!isConditionTrue())
		return -1;

	if (!HasInputFocus) {
		if (state != TOUCH_RELEASE)
			return 0; // Only change focus if touch releases within the input box
		if (GetSelection(x, y) >= 0) {
			// When changing focus, we don't scroll or change the cursor location
			PageManager::SetKeyBoardFocus(0);
			PageManager::NotifyCharInput(0);
			SetInputFocus(1);
			DrawCursor = true;
			mRendered = false;
		}
	} else {
		switch (state) {
		case TOUCH_HOLD:
		case TOUCH_REPEAT:
			break;
		case TOUCH_START:
			startSelection = GetSelection(x,y);
			lastX = x;
			DrawCursor = false;
			mRendered = false;
			break;

		case TOUCH_DRAG:
			// Check if we dragged out of the selection window
			if (GetSelection(x, y) == -1) {
				lastX = 0;
				break;
			}

			DrawCursor = false;

			// Provide some debounce on initial touches
			if (startSelection != -1 && abs(x - lastX) < 6) {
				break;
			}

			startSelection = -1;
			if (lastX != x)
				HandleTextLocation(x);
			break;

		case TOUCH_RELEASE:
			// We've moved the cursor location
			mRendered = false;
			DrawCursor = true;
			HandleCursorByTouch(x);
			break;
		}
	}
	return 0;
}

int GUIInput::NotifyVarChange(const std::string& varName, const std::string& value)
{
	GUIObject::NotifyVarChange(varName, value);

	if (varName == mVariable) {
		if (!isLocalChange) {
			UpdateDisplayText();
			HandleTextLocation(TW_INPUT_NO_UPDATE);
		} else
			isLocalChange = false;
		return 0;
	}
	if (varName.empty()) {
		UpdateDisplayText();
		HandleTextLocation(TW_INPUT_NO_UPDATE);
		HandleCursorByText();
	}
	return 0;
}

int GUIInput::NotifyKey(int key, bool down)
{
	if (!HasInputFocus || !down)
		return 1;

	switch (key)
	{
		case KEY_LEFT:
			if (mCursorLocation == 0)
				return 0; // we're already at the beginning
			if (mCursorLocation == -1) {
				if (displayValue.size() == 0) {
					cursorX = mRenderX;
					return 0;
				}
				mCursorLocation = displayValue.size() - 1;
			} else {
				mCursorLocation--;
			}
			mRendered = false;
			HandleCursorByText();
			return 0;

		case KEY_RIGHT:
			if (mCursorLocation == -1)
				return 0; // we're already at the end
			mCursorLocation++;
			if ((int)displayValue.size() <= mCursorLocation)
				mCursorLocation = -1;
			HandleCursorByText();
			mRendered = false;
			return 0;

		case KEY_HOME:
		case KEY_UP:
			if (displayValue.size() == 0)
				return 0;
			mCursorLocation = 0;
			mRendered = false;
			cursorX = mRenderX;
			return 0;

		case KEY_END:
		case KEY_DOWN:
			mCursorLocation = -1;
			mRendered = false;
			HandleCursorByText();
			return 0;
	}

	return 1;
}

int GUIInput::NotifyCharInput(int key)
{
	if (HasInputFocus) {
		if (key == KEYBOARD_BACKSPACE) {
			//Backspace
			if (mValue.size() > 0 && mCursorLocation != 0) {
				if (mCursorLocation == -1) {
					mValue.resize(mValue.size() - 1);
				} else {
					mValue.erase(mCursorLocation - 1, 1);
					mCursorLocation--;
				}
				isLocalChange = true;
				DataManager::SetValue(mVariable, mValue);
				UpdateDisplayText();
				HandleTextLocation(TW_INPUT_NO_UPDATE);
				HandleCursorByText();
			}
		} else if (key == KEYBOARD_SWIPE_LEFT) {
			// Delete all
			isLocalChange = true;
			if (mCursorLocation == -1) {
				DataManager::SetValue (mVariable, "");
				mValue = "";
				textWidth = 0;
				mCursorLocation = -1;
			} else {
				mValue.erase(0, mCursorLocation);
				DataManager::SetValue(mVariable, mValue);
				mCursorLocation = 0;
			}
			UpdateDisplayText();
			cursorX = mRenderX;
			scrollingX = 0;
			mRendered = false;
			return 0;
		} else if (key >= 32) {
			// Regular key
			if (HasAllowed && AllowedList.find((char)key) == string::npos) {
				return 0;
			}
			if (HasDisabled && DisabledList.find((char)key) != string::npos) {
				return 0;
			}
			if (MaxLen != 0 && mValue.size() >= MaxLen) {
				return 0;
			}
			if (mCursorLocation == -1) {
				mValue += key;
			} else {
				mValue.insert(mCursorLocation, 1, key);
				mCursorLocation++;
			}
			isLocalChange = true;
			DataManager::SetValue(mVariable, mValue);
			UpdateDisplayText();
			HandleTextLocation(TW_INPUT_NO_UPDATE);
			HandleCursorByText();
		} else if (key == KEYBOARD_ACTION) {
			// Action
			if (mAction) {
				unsigned inputLen = mValue.length();
				if (inputLen < MinLen)
					return 0;
				else if (MaxLen != 0 && inputLen > MaxLen)
					return 0;
				else
					return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
			}
		}
		return 0;
	} else {
		if (key == 0) {
			// Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
			mRendered = false;
			return 1;
		}
	}
	return 1;
}
