/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team

This file is part of OpenMoHAA source code.

OpenMoHAA source code 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 2 of the License,
or (at your option) any later version.

OpenMoHAA source code 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 OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

#include "ui_local.h"
#include "localization.h"

CLASS_DECLARATION( UIWidget, UIList, NULL )
{
	{ &W_LeftMouseDown,			&UIList::Pressed },
	{ &W_LeftMouseUp,			&UIList::Released },
	{ &EV_Layout_AddListItem,	&UIList::LayoutAddListItem },
	{ NULL, NULL }
};

UIList::UIList()
{
	m_arrow_width = 15.0;
	m_arrow_width = 0.0;
	m_currentItem = 0;
	m_next_arrow_region = 0;
	m_prev_arrow_region = 0;
	m_prev_arrow_depressed = 0;
	m_next_arrow_depressed = 0;

	AllowActivate(true);

	m_prev_arrow = uWinMan.RegisterShader("gfx/2d/arrow_left.tga");
	if (!m_prev_arrow) {
		uii.Sys_Printf("UIList::Ulist : Could not register shader gfx/2d/arrow_left.tga");
	}



	m_next_arrow = uWinMan.RegisterShader("gfx/2d/arrow_right.tga");
	if (!m_next_arrow) {
		uii.Sys_Printf("UIList::Ulist : Could not register shader gfx/2d/arrow_right.tga");
	}
}

UIList::~UIList()
{
	for (int i = m_itemlist.NumObjects(); i > 0; i--)
	{
		UIListItem* item = m_itemlist.ObjectAt(i);
		m_itemlist.RemoveObjectAt(i);
		delete item;
	}

	if (m_prev_arrow_region) delete m_prev_arrow_region;
	if (m_next_arrow_region) delete m_next_arrow_region;
}

void UIList::Draw
	(
	void
	)

{
	UpdateUIElement();

	// draw the item text
	if (m_currentItem)
	{
		str itemText;
		UIListItem *item = m_itemlist.ObjectAt(m_currentItem);
		if (item->itemalias)
		{
			itemText = item->itemalias;
		}
		else if (item->itemname)
		{
			itemText = item->itemname;
		}

		float textX = 0.5f * m_frame.size.width - 0.5f * m_font->getWidth(itemText, -1);
		float textY = 0.5f * (m_frame.size.height - m_font->getHeight(m_bVirtual ? m_vVirtualScale : uid.scaleRes)) - 1.0f;
		m_font->setColor(m_foreground_color);
		const char *text = Sys_LV_CL_ConvertString(itemText);
		m_font->Print(textX, textY, text, -1, m_bVirtual ? m_vVirtualScale : NULL);
	}

	// draw the previous arrow
	Draw3DBox(
		0.0f,
		0.0f,
		m_arrow_width,
		m_frame.size.height,
		m_prev_arrow_depressed,
		m_border_color,
		m_local_alpha);

	float height = m_frame.size.height - 4.0;
	float width = m_arrow_width - 4.0;
	uii.Rend_DrawPicStretched(
		2.0f,
		2.0f,
		width,
		height,
		0.0f,
		0.0f,
		1.0f,
		1.0f,
		m_prev_arrow->GetMaterial());

	// draw the next arrow
	float x = m_frame.size.width - m_arrow_width;
	float y = 0.0f;
	Draw3DBox(
		x,
		y,
		m_arrow_width,
		m_frame.size.height,
		m_next_arrow_depressed,
		m_border_color,
		m_local_alpha);

	uii.Rend_DrawPicStretched(
		x + 2.0f,
		y + 2.0f,
		width,
		height,
		0.0f,
		0.0f,
		1.0f,
		1.0f,
		m_next_arrow->GetMaterial());
}

qboolean UIList::KeyEvent
	(
	int key,
	unsigned int time
	)

{
	switch (key)
	{
	case K_RIGHTARROW:
		ScrollNext();
		UpdateData();
		if (m_commandhandler) {
			m_commandhandler(m_itemlist.ObjectAt(m_currentItem)->itemname.c_str(), NULL);
		}
		return qtrue;
	case K_LEFTARROW:
		ScrollPrev();
		UpdateData();
		if (m_commandhandler) {
			m_commandhandler(m_itemlist.ObjectAt(m_currentItem)->itemname.c_str(), NULL);
		}
		return qtrue;
	default:
		return qfalse;
	}

}

void UIList::CharEvent
	(
	int ch
	)

{
}

void UIList::Pressed
	(
	Event *ev
	)

{
	m_held = qtrue;
	m_depressed = qtrue;

	float mouse_xpos = ev->GetFloat(1);
	float mouse_ypos = ev->GetFloat(2);
	int buttons = ev->GetInteger(3); // unused

	FrameInitialized();

	// previous arrow is clicked
	if (m_prev_arrow_region->contains(mouse_xpos, mouse_ypos))
	{
		m_prev_arrow_depressed = qtrue;
		ScrollPrev();
		UpdateData();
		return;
	}

	// next arrow is clicked
	if (m_next_arrow_region->contains(mouse_xpos, mouse_ypos))
	{
		m_next_arrow_depressed = qtrue;
		ScrollNext();
		UpdateData();
	}
}

void UIList::Released
	(
	Event *ev
	)

{
	m_held = qfalse;
	m_depressed = qfalse;
	m_prev_arrow_depressed = qfalse;
	m_next_arrow_depressed = qfalse;
}

void UIList::ScrollNext
	(
	void
	)

{
	m_currentItem++;
	if (m_currentItem > m_itemlist.NumObjects()) {
		m_currentItem = m_itemlist.NumObjects();
	}
}

void UIList::ScrollPrev
	(
	void
	)

{
	m_currentItem--;
	if (m_currentItem < 1) {
		m_currentItem = 1;
	}
}

void UIList::FrameInitialized
	(
	void
	)

{
	m_prev_arrow_region = new UIRect2D(m_clippedframe.pos.x, m_clippedframe.pos.y, m_arrow_width, m_frame.size.height);
	m_next_arrow_region = new UIRect2D(m_clippedframe.size.width - m_arrow_width + m_clippedframe.pos.x, m_clippedframe.pos.y, m_arrow_width, m_frame.size.height);
}

void UIList::LayoutAddListItem
	(
	Event *ev
	)

{
	str item = ev->GetString(1);
	str alias;
	if (ev->NumArgs() > 1)
	{
		alias = ev->GetString(2);
	}

	AddItem(item, alias);
}

void UIList::AddItem
(
str item,
str alias
)

{
	UIListItem *listItem = new UIListItem();
	listItem->itemname = item;
	listItem->itemalias = alias;

	m_itemlist.AddObject(listItem);
	m_currentItem = 1;
}

void UIList::UpdateUIElement
	(
	void
	)

{
	if (!m_cvarname)
	{
		return;
	}

	const char *cvarstring = UI_GetCvarString(m_cvarname, NULL);
	if (!cvarstring)
	{
		m_currentItem = 1;
		UpdateData();
		return;
	}

	for (int i = 1; i <= m_itemlist.NumObjects(); i++)
	{
		UIListItem *obj = m_itemlist.ObjectAt(i);
		if (obj->itemname == cvarstring)
		{
			m_currentItem = i;
			break;
		}
	}
}

void UIList::UpdateData
	(
	void
	)

{
	if (!m_currentItem)
	{
		return;
	}

	if (m_cvarname)
	{
		UIListItem *item = m_itemlist.ObjectAt(m_currentItem);
		if (item->itemname)
		{
			uii.Cvar_Set(m_cvarname, item->itemname);
		}
	}

	if (m_command)
	{
		UIListItem *item = m_itemlist.ObjectAt(m_currentItem);
		m_command.append(' ');
		m_command.append(item->itemname);
		m_command.append('\n');
		Cbuf_AddText(m_command.c_str());
	}
}

CLASS_DECLARATION( UIList, UIListIndex, NULL )
{
	{ NULL, NULL }
};

qboolean UIListIndex::KeyEvent
	(
	int key,
	unsigned int time
	)

{
	switch (key)
	{
	case K_RIGHTARROW:
		ScrollNext();
		UpdateData();
		return qtrue;
	case K_LEFTARROW:
		ScrollPrev();
		UpdateData();
		return qtrue;
	default:
		return qfalse;
	}
}
