/*
	Copyright 2017 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 <string>

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

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

MouseCursor::MouseCursor(int resX, int resY)
{
	ResetData(resX, resY);
}

MouseCursor::~MouseCursor()
{
}

void MouseCursor::ResetData(int resX, int resY)
{
	m_resX = resX;
	m_resY = resY;
	m_moved = false;
	m_speedMultiplier = 2.5f;
	m_image = NULL;
	m_present = false;

	ConvertStrToColor("red", &m_color);

	SetRenderPos(resX/2, resY/2, 10, 10);
}

void MouseCursor::LoadData(xml_node<>* node)
{
	xml_attribute<>* attr;
	xml_node<>* child;

	child = FindNode(node, "placement");
	if (child)
		LoadPlacement(child, &mRenderX, &mRenderY, &mRenderW, &mRenderH);

	child = FindNode(node, "background");
	if (child)
	{
		m_color = LoadAttrColor(child, "color", m_color);
		m_image = LoadAttrImage(child, "resource");
		if (m_image && m_image->GetResource())
		{
			mRenderW = m_image->GetWidth();
			mRenderH = m_image->GetHeight();
		}
	}

	child = FindNode(node, "speed");
	if (child)
	{
		attr = child->first_attribute("multiplier");
		if (attr)
			m_speedMultiplier = atof(attr->value());
	}
}

int MouseCursor::Render(void)
{
	if (!m_present)
		return 0;

	if (m_image && m_image->GetResource())
	{
		gr_blit(m_image->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
	}
	else
	{
		gr_color(m_color.red, m_color.green, m_color.blue, m_color.alpha);
		gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
	}
	return 0;
}

int MouseCursor::Update(void)
{
	if (m_present != ev_has_mouse())
	{
		m_present = ev_has_mouse();
		if (m_present)
			SetRenderPos(m_resX/2, m_resY/2);
		return 2;
	}

	if (m_present && m_moved)
	{
		m_moved = false;
		return 2;
	}
	return 0;
}

int MouseCursor::SetRenderPos(int x, int y, int w, int h)
{
	if (x == mRenderX && y == mRenderY)
		m_moved = true;

	return RenderObject::SetRenderPos(x, y, w, h);
}

void MouseCursor::Move(int deltaX, int deltaY)
{
	if (deltaX != 0)
	{
		mRenderX += deltaX*m_speedMultiplier;
		mRenderX = (std::min)(mRenderX, m_resX);
		mRenderX = (std::max)(mRenderX, 0);

		m_moved = true;
	}

	if (deltaY != 0)
	{
		mRenderY += deltaY*m_speedMultiplier;
		mRenderY = (std::min)(mRenderY, m_resY);
		mRenderY = (std::max)(mRenderY, 0);

		m_moved = true;
	}
}

void MouseCursor::GetPos(int& x, int& y)
{
	x = mRenderX;
	y = mRenderY;
}
