/*
   client/controlsettingsmenu.cc
   This file is part of the Osirion project and is distributed under
   the terms of the GNU General Public License version 2
*/

#include "client/controlsettingsmenu.h"
#include "client/closeiconbutton.h"
#include "client/input.h"
#include "ui/button.h"
#include "ui/iconbutton.h"
#include "ui/label.h"
#include "ui/listview.h"
#include "ui/ui.h"

namespace client {
	
class ControlListItem : public ui::ListItem
{
public:
	ControlListItem(ui::ListView *parent, Control *control) : ui::ListItem(parent, "")
	{
		set_border(false);
		
		_namelabel = new ui::Label(this);
		_namelabel->set_border(true);
		_namelabel->set_background(false);
		_namelabel->set_alignment(ui::AlignVCenter | ui::AlignLeft);
		
		_keylabel = new ui::Button(this);
		_keylabel->set_border(true);
		_keylabel->set_background(false);
		_keylabel->set_alignment(ui::AlignCenter);
		
		set_control(control);
		
	}
	
	virtual ~ControlListItem()
	{
	}
	
	inline Control *control()
	{
		return _control;
	}
	
	void refresh()
	{
		if (_control)
		{
			_namelabel->set_text(_control->name());
			_keylabel->set_text(_control->keyname());
		}
		else 
		{
			_namelabel->clear();
			_keylabel->clear();
		}
	}
	
	void set_control(Control *control)
	{
		_control = control;
		refresh();
	}
	
protected:	
	virtual void resize()
	{
		const float w = width() * 0.5f;
		const float h = height();
		
		_namelabel->set_size(w, h);
		_namelabel->set_location(0.0f, 0.0f);
		
		_keylabel->set_size(width() - w, h);
		_keylabel->set_location(width() - w, 0.0f);
		
	}
	
	virtual bool on_emit(Widget *sender, const Event event, void *data)
	{
		if (event == ui::Widget::EventButtonClicked)
		{
			if (sender == _keylabel)
			{
				emit(EventListItemClicked);
				return true;
			}
		}
		return ui::ListItem::on_emit(sender, event, data);
	}
	
private:
	ui::Label 	*_namelabel;
	ui::Button 	*_keylabel;
	
	Control		*_control;
	
};

class ControlKeyWindow : public ui::Window
{
public:
	ControlKeyWindow(ui::Widget *parent = 0) : ui::Window(parent)
	{
		set_border(false);
		set_background(false);
		set_label("controlkeywindow");
	
		_frame = new ui::Window(this);
		_frame->set_border(true);
		_frame->set_background(true);
	
		_namelabel = new ui::Label(_frame);
		_namelabel->set_border(false);
		_namelabel->set_background(false);
		_namelabel->set_alignment(ui::AlignCenter);
		
		_keylabel = new ui::Label(_frame);
		_keylabel->set_border(false);
		_keylabel->set_background(false);
		_keylabel->set_alignment(ui::AlignCenter);
	
		_okbutton = new ui::Button(_frame, "OK");
		_cancelbutton = new ui::Button(_frame, "Cancel");
	}
	
	virtual ~ControlKeyWindow()
	{
	}
	
	inline const std::string &key() const
	{
		return _keylabel->text();
	}
	
	void set_control(Control *control)
	{
		_control = control;
		_namelabel->set_text("Press key ^F" + _control->name() );
		_keylabel->set_text(_control->keyname());
	}
	
protected:
	virtual void resize()
	{
		const float padding =  ui::UI::padding;
		
		set_size(parent()->size());
		
		_frame->set_size(
			ui::UI::elementsize.width() * 3.0f, 
			ui::UI::elementsize.width() * 1.5f
		);	
		_frame->set_location(
			(width() - _frame->width()) * 0.5f,
			(height() - _frame->height()) * 0.5f
		);

		const float h =  ui::root()->font_large()->height() * 2.0f;
		_namelabel->set_size(_frame->width() - padding * 2.0f, h * 2.0f);
		_namelabel->set_location(padding, padding);
		
		_keylabel->set_size(_frame->width() - padding * 2.0f, h);
		_keylabel->set_location(padding, _namelabel->bottom() + padding);
		
		_okbutton->set_size(ui::UI::elementsize);
		_cancelbutton->set_size(ui::UI::elementsize);
		
		const float l = (_frame->width() - _okbutton->width() - _cancelbutton->width() - padding * 2.0f) * 0.5f;
		_okbutton->set_location(l, _frame->height() - _okbutton->height() - padding);
		_cancelbutton->set_location(_okbutton->right() + padding, _frame->height() - _cancelbutton->height() - padding);

	}
	
	void capture_keypress()
	{
	std::string keyname;
		if (input::last_key_pressed()) {
			Key::Modifier mod = input::modifier();
			if (mod == Key::Shift)
				keyname.assign("shift+");
			else if (mod == Key::Ctrl)
				keyname.assign("ctrl+");
			else if (mod == Key::Alt)
				keyname.assign("alt+");
			keyname.append(input::last_key_pressed()->name());
		}
		_keylabel->set_text(keyname);
	}
	
	virtual bool on_mousepress(const unsigned int button)
	{
		capture_keypress();
		return true;
	
	}
	
	virtual bool on_mousewheel(const math::Vector2f & direction)
	{
		capture_keypress();
		return true;
	}
	
	virtual bool on_keypress(const int key, const unsigned int modifier)
	{
		if (key == SDLK_ESCAPE)
		{
			hide();
			return true;
		}
		else 
		{
			capture_keypress();
			return true;
		}
		return false;
	}
	
	virtual bool on_emit(Widget *sender, const Event event, void *data)
	{
		if (event == Widget::EventButtonClicked)
		{
			if (sender == _okbutton) 
			{
				if (_control->keyname().size())
				{
					input::keyboard->unbind(_control->keyname());
				}
				
				_control->set_keyname(_keylabel->text());
				
				if (_control->keyname().size())
				{
					input::keyboard->bind(_control->keyname(), _control->command());
				}
				
				input::keyboard->load_controls();
				
				hide();
				return true;
			}
			else if (sender == _cancelbutton)
			{
				hide();
				return true;
			}
		}
		return ui::Window::on_emit(sender, event, data);
	}
	
private:	
	ui::Window	*_frame;
	
	ui::Label	*_namelabel;
	ui::Label	*_keylabel;
	ui::Button	*_okbutton;
	ui::Button	*_cancelbutton;
	
	Control		*_control;
};
	
ControlSettingsMenu::ControlSettingsMenu(ui::Widget *parent, const char *label) : ui::Window(parent)
{
	set_label(label);
	set_border(true);
	set_background(true);
	set_font(ui::root()->font_small());
	
	// window title
	_titlelabel = new ui::Label(this);
	_titlelabel->set_label("title");
	_titlelabel->set_background(false);
	_titlelabel->set_border(false);
	_titlelabel->set_font(ui::root()->font_large());
	_titlelabel->set_alignment(ui::AlignCenter);
	_titlelabel->set_text("CONTROLS");
	
	// close button
	_closebutton = new CloseIconButton(_titlelabel);
	
	// command listview
	_controlslistview = new ui::ListView(this);
	_controlslistview->set_background(true);
	
	_controlkeywindow = new ControlKeyWindow(this);
	_controlkeywindow->hide();
}

ControlSettingsMenu::~ControlSettingsMenu()
{
}

void ControlSettingsMenu::refresh()
{
	_controlslistview->clear();
	
	input::keyboard->load_controls();
	
	for (Keyboard::Controls::iterator cit = input::keyboard->controls().begin(); cit != input::keyboard->controls().end(); ++cit)
	{
		ui::ListItem *listitem = new ControlListItem(_controlslistview, (*cit));
		listitem->set_font(ui::root()->font_tiny());
		listitem->set_height(listitem->font()->height() * 2.0f);
	}
	
	_controlslistview->event_resize();
}

void ControlSettingsMenu::show()
{
	refresh();
	ui::Window::show();
}

void ControlSettingsMenu::apply()
{
}

void ControlSettingsMenu::resize()
{
	const float padding =  ui::UI::padding;
	
	// resize title label
	_titlelabel->set_size(width() - padding * 2.0f, _titlelabel->font()->height());	
	_titlelabel->set_location(padding, padding);

	// resize close button
	_closebutton->set_size(_titlelabel->font()->height(), _titlelabel->font()->height());
	_closebutton->set_location(_titlelabel->width() - _closebutton->width(), 0);
	
	// resize listview
	_controlslistview->set_location(_titlelabel->left(), _titlelabel->bottom() + padding);	
	_controlslistview->set_size(_titlelabel->width(), height() - _titlelabel->bottom() - padding * 2.0f);
}

bool ControlSettingsMenu::on_emit(ui::Widget *sender, const ui::Widget::Event event, void *data)
{
	if (sender == _closebutton)
	{
		if (event == ui::Widget::EventButtonClicked)
		{
			parent()->hide();
			return true;
		}
	}
	else if (sender == _controlslistview)
	{
		if (event == ui::Widget::EventListViewChanged)
		{
			if (_controlslistview->selected())
			{
				ControlListItem *listitem = static_cast<ControlListItem *>(_controlslistview->selected());
				_controlkeywindow->set_control(listitem->control());
				_controlkeywindow->show();
			}
			return true;
		}
	}
	else if (sender == _controlkeywindow)
	{
		if (event == ui::Widget::EventWindowHide)
		{
			for (ui::Widget::Children::iterator it = _controlslistview->children().begin(); it != _controlslistview->children().end(); ++it)
			{	
				ControlListItem *listitem = dynamic_cast<ControlListItem *>(*it);				
				if  (listitem)
				{
					listitem->refresh();
				}
				
			}
			return true;
		}
		
	}
	return Window::on_emit(sender, event, data);
}

} // namespace client