//////////////////////////////////////////////////////////////////////
// This file is part of Remere's Map Editor
//////////////////////////////////////////////////////////////////////
// This program 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.
// 
// This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////////
// $URL: http://svn.rebarp.se/svn/RME/trunk/source/palette_house.hpp $
// $Id: palette_house.hpp 310 2010-02-26 18:03:48Z admin $

#include "main.h"

#include "palette_house.h"

#include "settings.h"

#include "brush.h"
#include "editor.h"
#include "map.h"

#include "application.h"
#include "map_display.h"

#include "house_brush.h"
#include "house_exit_brush.h"
#include "spawn_brush.h"

// ============================================================================
// House palette

BEGIN_EVENT_TABLE(HousePalettePanel, PalettePanel)
	EVT_TIMER(PALETTE_LAYOUT_FIX_TIMER, HousePalettePanel::OnLayoutFixTimer)

	EVT_CHOICE(PALETTE_HOUSE_TOWN_CHOICE, HousePalettePanel::OnTownChange)

	EVT_LISTBOX(PALETTE_HOUSE_LISTBOX, HousePalettePanel::OnListBoxChange)
	EVT_LISTBOX_DCLICK(PALETTE_HOUSE_LISTBOX, HousePalettePanel::OnListBoxDoubleClick)

	EVT_BUTTON(PALETTE_HOUSE_ADD_HOUSE, HousePalettePanel::OnClickAddHouse)
	EVT_BUTTON(PALETTE_HOUSE_EDIT_HOUSE, HousePalettePanel::OnClickEditHouse)
	EVT_BUTTON(PALETTE_HOUSE_REMOVE_HOUSE, HousePalettePanel::OnClickRemoveHouse)

	EVT_TOGGLEBUTTON(PALETTE_HOUSE_BRUSH_BUTTON, HousePalettePanel::OnClickHouseBrushButton)
	EVT_TOGGLEBUTTON(PALETTE_HOUSE_SELECT_EXIT_BUTTON, HousePalettePanel::OnClickSelectExitButton)
END_EVENT_TABLE()

HousePalettePanel::HousePalettePanel(wxWindow* parent, wxWindowID id) :
	PalettePanel(parent, id),
	map(nullptr),
	do_resize_on_display(true),
	fix_size_timer(this, PALETTE_LAYOUT_FIX_TIMER)
{
	wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
	wxSizer* tmpsizer;

	wxSizer* sidesizer = newd wxStaticBoxSizer(wxVERTICAL, this, wxT("Houses"));
	town_choice = newd wxChoice(this, PALETTE_HOUSE_TOWN_CHOICE, wxDefaultPosition, wxDefaultSize, (int)0, (const wxString*)nullptr);
	sidesizer->Add(town_choice, 0, wxEXPAND);

	house_list = newd wxListBox(this, PALETTE_HOUSE_LISTBOX, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_SINGLE | wxLB_NEEDED_SB | wxLB_SORT);
	sidesizer->Add(house_list, 1, wxEXPAND);

	tmpsizer = newd wxBoxSizer(wxHORIZONTAL);
	tmpsizer->Add(add_house_button = newd wxButton(this, PALETTE_HOUSE_ADD_HOUSE, wxT("Add"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags(1).Right());
	tmpsizer->Add(edit_house_button = newd wxButton(this, PALETTE_HOUSE_EDIT_HOUSE, wxT("Edit"), wxDefaultPosition, wxSize(50, -1)), wxSizerFlags(1).Right());
	tmpsizer->Add(remove_house_button = newd wxButton(this, PALETTE_HOUSE_REMOVE_HOUSE, wxT("Remove"), wxDefaultPosition, wxSize(70, -1)), wxSizerFlags(1).Right());
	sidesizer->Add(tmpsizer, wxSizerFlags(0).Right());

	topsizer->Add(sidesizer, 1, wxEXPAND);

	// Temple position
	sidesizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, wxT("Brushes"), wxDefaultPosition, wxSize(150, 200)), wxVERTICAL);

	//sidesizer->Add(180, 1, wxEXPAND);

	tmpsizer = newd wxBoxSizer(wxHORIZONTAL);
	house_brush_button = newd wxToggleButton(this, PALETTE_HOUSE_BRUSH_BUTTON, wxT("House tiles"));
	tmpsizer->Add(house_brush_button);
	sidesizer->Add(tmpsizer, wxSizerFlags(1).Center());

	tmpsizer = newd wxBoxSizer(wxHORIZONTAL);
	select_position_button = newd wxToggleButton(this, PALETTE_HOUSE_SELECT_EXIT_BUTTON, wxT("Select Exit"));
	tmpsizer->Add(select_position_button);
	sidesizer->Add(tmpsizer, wxSizerFlags(1).Center());

	topsizer->Add(sidesizer, 0, wxEXPAND);

	SetSizerAndFit(topsizer);
}

HousePalettePanel::~HousePalettePanel() {
	// ...
}

void HousePalettePanel::SetMap(Map* m) {
	gui.house_brush->setHouse(nullptr);
	map = m;
	OnUpdate();
}

void HousePalettePanel::OnSwitchIn() {
	PalettePanel::OnSwitchIn();
	// Extremely ugly hack to fix layout issue
	if(do_resize_on_display) {
		fix_size_timer.Start(100, true);
		do_resize_on_display = false;
	}
}

void HousePalettePanel::OnLayoutFixTimer(wxTimerEvent& WXUNUSED(event)) {
	wxWindow* w = this;
	while((w = w->GetParent()) && dynamic_cast<PaletteWindow*>(w) == nullptr);
	
	if(w)
	{
		w->SetSize(w->GetSize().GetWidth(), w->GetSize().GetHeight() + 1);
		w->SetSize(w->GetSize().GetWidth(), w->GetSize().GetHeight() - 1);
	}
}

void HousePalettePanel::SelectFirstBrush() {
	SelectHouseBrush();
}

Brush* HousePalettePanel::GetSelectedBrush() const {
	if(select_position_button->GetValue()) {
		House* house = GetCurrentlySelectedHouse();
		if(house)
			gui.house_exit_brush->setHouse(house);
		return (gui.house_exit_brush->getHouseID() != 0? gui.house_exit_brush : nullptr);
	} else if(house_brush_button->GetValue()) {
		gui.house_brush->setHouse(GetCurrentlySelectedHouse());
		return (gui.house_brush->getHouseID() != 0? gui.house_brush : nullptr);
	} else {
		return nullptr;
	}
}

bool HousePalettePanel::SelectBrush(const Brush* whatbrush) {
	const HouseBrush* house_brush = dynamic_cast<const HouseBrush*>(whatbrush);
	const SpawnBrush* spawn_brush = dynamic_cast<const SpawnBrush*>(whatbrush);

	if(house_brush && map != nullptr) {
		for(HouseMap::iterator house_iter = map->houses.begin();
				house_iter != map->houses.end();
				++house_iter)
		{
			if(house_iter->second->id == house_brush->getHouseID()) {
				for(uint32_t i = 0; i < town_choice->GetCount(); ++i) {
					Town* town = reinterpret_cast<Town*>(town_choice->GetClientData(i));
					// If it's "No Town" (nullptr) select it, or if it has the same town ID as the house
					if(town == nullptr || town->getID() == house_iter->second->townid) {
						SelectTown(i);
						for(uint32_t j = 0; j < house_list->GetCount(); ++j) {
							if(house_iter->second->id == reinterpret_cast<House*>(house_list->GetClientData(j))->id) {
								SelectHouse(j);
								return true;
							}
						}
						return true;
					}
				}
			}
		}
	} else if(spawn_brush) {
		SelectExitBrush();
	}
	return false;
}

int HousePalettePanel::GetSelectedBrushSize() const {
	return 0;
}

PaletteType HousePalettePanel::GetType() const {
	return TILESET_HOUSE;
}

void HousePalettePanel::SelectTown(size_t index) {
	ASSERT(town_choice->GetCount() >= index);

	if(map == nullptr || town_choice->GetCount() == 0) {
		// No towns :(
		add_house_button->Enable(false);
	} else {
		Town* what_town = reinterpret_cast<Town*>(town_choice->GetClientData(index));

		// Clear the old houselist
		house_list->Clear();

		for(HouseMap::iterator house_iter = map->houses.begin();
				house_iter != map->houses.end();
				++house_iter)
		{
			if(what_town) {
				if(house_iter->second->townid == what_town->getID()) {
					house_list->Append(wxstr(house_iter->second->getDescription()), house_iter->second);
				}
			} else {
				// "No Town" selected!
				if(map->towns.getTown(house_iter->second->townid) == false) {
					// The town doesn't exist
					house_list->Append(wxstr(house_iter->second->getDescription()), house_iter->second);
				}
			}
		}

		// Select first house
		SelectHouse(0);
		town_choice->SetSelection(index);
		add_house_button->Enable(what_town != nullptr);
		ASSERT(what_town == nullptr || add_house_button->IsEnabled() || IsEnabled() == false);
	}
}

void HousePalettePanel::SelectHouse(size_t index) {
	ASSERT(house_list->GetCount() >= index);

	if(house_list->GetCount() > 0) {
		edit_house_button->Enable(true);
		remove_house_button->Enable(true);
		select_position_button->Enable(true);
		house_brush_button->Enable(true);
		// Select the house
		house_list->SetSelection(index);
		SelectHouseBrush();
	} else {
		// No houses :(
		edit_house_button->Enable(false);
		remove_house_button->Enable(false);
		select_position_button->Enable(false);
		house_brush_button->Enable(false);
	}

	SelectHouseBrush();
	gui.RefreshView();
}

House* HousePalettePanel::GetCurrentlySelectedHouse() const {
	if(house_list->GetCount() > 0) {
		return reinterpret_cast<House*>(house_list->GetClientData(house_list->GetSelection()));
	}
	return nullptr;
}

void HousePalettePanel::SelectHouseBrush() {
	if(house_list->GetCount() > 0) {
		house_brush_button->SetValue(true);
		select_position_button->SetValue(false);
	} else {
		house_brush_button->SetValue(false);
		select_position_button->SetValue(false);
	}
}

void HousePalettePanel::SelectExitBrush() {
	if(house_list->GetCount() > 0) {
		house_brush_button->SetValue(false);
		select_position_button->SetValue(true);
	}
}

void HousePalettePanel::OnUpdate()
{
	if(map == nullptr)
		return;
	
	int old_town_selection = town_choice->GetSelection();

	town_choice->Clear();
	house_list->Clear();

	if(map->towns.count() != 0)
	{
		// Create choice control
		for(TownMap::iterator town_iter = map->towns.begin();
				town_iter != map->towns.end();
				++town_iter)
		{
			town_choice->Append(wxstr(town_iter->second->getName()), town_iter->second);
		}
		town_choice->Append(wxT("No Town"), (void*)(nullptr));
		if(old_town_selection <= 0)
			SelectTown(0);
		else if((size_t)old_town_selection <= town_choice->GetCount())
			SelectTown(old_town_selection);
		else
			SelectTown(old_town_selection-1);
		
		house_list->Enable(true);
	}
	else
	{
		town_choice->Append(wxT("No Town"), (void*)(nullptr));
		select_position_button->Enable(false);
		select_position_button->SetValue(false);
		house_brush_button->Enable(false);
		house_brush_button->SetValue(false);
		add_house_button->Enable(false);
		edit_house_button->Enable(false);
		remove_house_button->Enable(false);

		SelectTown(0);
	}
}

void HousePalettePanel::OnTownChange(wxCommandEvent& event)
{
	SelectTown(event.GetSelection());
	gui.SelectBrush();
}

void HousePalettePanel::OnListBoxChange(wxCommandEvent& event)
{
	SelectHouse(event.GetSelection());
	gui.SelectBrush();
}

void HousePalettePanel::OnListBoxDoubleClick(wxCommandEvent& event)
{
	House* house = reinterpret_cast<House*>(event.GetClientData());
	// I find it extremly unlikely that one actually wants the exit at 0,0,0, so just treat it as the null value
	if(house && house->getExit() != Position(0,0,0)) {
		gui.CenterOnPosition(house->getExit());
	}
}

void HousePalettePanel::OnClickHouseBrushButton(wxCommandEvent& event)
{
	SelectHouseBrush();
	gui.SelectBrush();
}

void HousePalettePanel::OnClickSelectExitButton(wxCommandEvent& event)
{
	SelectExitBrush();
	gui.SelectBrush();
}

void HousePalettePanel::OnClickAddHouse(wxCommandEvent& event)
{
	if(map == nullptr)
		return;

	House* new_house = newd House(*map);
	new_house->id = map->houses.getEmptyID();
	
	std::ostringstream os;
	os << "Unnamed House #" << new_house->id;
	new_house->name = os.str();
	Town* town = reinterpret_cast<Town*>(town_choice->GetClientData(town_choice->GetSelection()));
	
	ASSERT(town);
	new_house->townid = town->getID();

	map->houses.addHouse(new_house);
	house_list->Append(wxstr(new_house->getDescription()), new_house);
	SelectHouse(house_list->FindString(wxstr(new_house->getDescription())));
	gui.SelectBrush();
	refresh_timer.Start(300, true);
}

void HousePalettePanel::OnClickEditHouse(wxCommandEvent& event)
{
	if(house_list->GetCount() == 0)
		return;
	if(map == nullptr)
		return;

	House* house = reinterpret_cast<House*>(house_list->GetClientData(house_list->GetSelection()));
	if(house)
	{
		wxDialog* d = newd EditHouseDialog(gui.root, map, house);
		int ret = d->ShowModal();
		if(ret == 1)
		{
			// Something changed, change name of house
			house_list->SetString(house_list->GetSelection(), wxstr(house->getDescription()));
			refresh_timer.Start(300, true);
		}
	}
}

void HousePalettePanel::OnClickRemoveHouse(wxCommandEvent& event)
{
	int selection_index = house_list->GetSelection();
	if(selection_index != wxNOT_FOUND)
	{
		House* house = reinterpret_cast<House*>(house_list->GetClientData(selection_index));
		map->houses.removeHouse(house);
		house_list->Delete(selection_index);
		refresh_timer.Start(300, true);

		if(int(house_list->GetCount()) <= selection_index)
		{
			selection_index -= 1;
		}

		if(selection_index >= 0 && house_list->GetCount())
		{
			house_list->SetSelection(selection_index);
		}
		gui.SelectBrush();
	}
	gui.RefreshView();
}

// ============================================================================
// House Edit Dialog

BEGIN_EVENT_TABLE(EditHouseDialog, wxDialog)
	EVT_BUTTON(wxID_OK, EditHouseDialog::OnClickOK)
	EVT_BUTTON(wxID_CANCEL, EditHouseDialog::OnClickCancel)
END_EVENT_TABLE()

EditHouseDialog::EditHouseDialog(wxWindow* parent, Map* map, House* house) :
	wxDialog(parent, wxID_ANY, wxT("House"), wxDefaultPosition, wxSize(250,160)),
	map(map),
	what_house(house)
{
	ASSERT(map);
	ASSERT(house);

	// Create topsizer
	wxSizer* sizer = newd wxBoxSizer(wxVERTICAL);
	wxSizer* tmpsizer;

	house_name = wxstr(house->name);
	house_id = i2ws(house->id);
	house_rent = i2ws(house->rent);

	// House options
	tmpsizer = newd wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Name"));
	name_field = newd wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(230,20), 0, wxTextValidator(wxFILTER_ASCII, &house_name));
	tmpsizer->Add(name_field);
 
	sizer->Add(tmpsizer, wxSizerFlags().Border(wxALL, 20));

	tmpsizer = newd wxStaticBoxSizer(wxHORIZONTAL, this, wxT("Rent / ID"));
	rent_field = newd wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(160,20), 0, wxTextValidator(wxFILTER_NUMERIC, &house_rent));
	tmpsizer->Add(rent_field);
	id_field = newd wxTextCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxSize(70,20), 0, wxTextValidator(wxFILTER_NUMERIC, &house_id));
	id_field->Enable(false);
	tmpsizer->Add(id_field);
	sizer->Add(tmpsizer, wxSizerFlags().Border(wxALL, 20));
	
	// House options
	guildhall_field = newd wxCheckBox(this, wxID_ANY, wxT("Guildhall"), wxDefaultPosition);
 
	sizer->Add(guildhall_field, wxSizerFlags().Border(wxRIGHT | wxLEFT | wxBOTTOM, 20));
	guildhall_field->SetValue(house->guildhall);

	// OK/Cancel buttons
	tmpsizer = newd wxBoxSizer(wxHORIZONTAL);
	tmpsizer->Add(newd wxButton(this, wxID_OK, wxT("OK")), wxSizerFlags(1).Center());
	tmpsizer->Add(newd wxButton(this, wxID_CANCEL, wxT("Cancel")), wxSizerFlags(1).Center());
	sizer->Add(tmpsizer, wxSizerFlags(1).Center().Border(wxRIGHT | wxLEFT | wxBOTTOM, 20));

	SetSizerAndFit(sizer);
}

EditHouseDialog::~EditHouseDialog() {
	// ...
}

void EditHouseDialog::OnClickOK(wxCommandEvent& WXUNUSED(event)) {
	if(Validate() && TransferDataFromWindow()) {
		// Verify the newd information
		long new_house_rent;
		house_rent.ToLong(&new_house_rent);

		if(new_house_rent < 0) {
			gui.PopupDialog(this, wxT("Error"), wxT("House rent cannot be less than 0."), wxOK);
			return;
		}

		if(house_name.length() == 0) {
			gui.PopupDialog(this, wxT("Error"), wxT("House name cannot be nil."), wxOK);
			return;
		}

		if(settings.getInteger(Config::WARN_FOR_DUPLICATE_ID)) {
			Houses& houses = map->houses;
			for(HouseMap::const_iterator house_iter = houses.begin();
					house_iter != houses.end();
					++house_iter)
			{
				House* house = house_iter->second;
				ASSERT(house);
				if(wxstr(house->name) == house_name && house->id != what_house->id) {
					int ret = gui.PopupDialog(this, wxT("Warning"), wxT("This house name is already in use, are you sure you want to continue?"), wxYES | wxNO);
					if(ret == wxID_NO) {
						return;
					}
				}
			}
		}

		// Transfer to house
		what_house->name = nstr(house_name);
		what_house->rent = new_house_rent;
		what_house->guildhall = guildhall_field->GetValue();

		EndModal(1);
	}
}

void EditHouseDialog::OnClickCancel(wxCommandEvent& WXUNUSED(event)) {
	// Just close this window
	EndModal(0);
}
