/*
        Copyright 2012 to 2020 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 "minuitwrp/truetype.hpp"

#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");
		if (mFont && mFont->GetResource())
			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 = twrpTruetype::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 = twrpTruetype::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 = twrpTruetype::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;
	}

	// 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;

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