/* $Id: copy_paste_gui.cpp 4998 2006-05-28 07:45:14Z Frostregen $ */

#include "stdafx.h"
#include "openttd.h"
#include "gui.h"
#include "window_gui.h"
#include "viewport_type.h"
#include "viewport_func.h"
#include "gfx_func.h"
#include "strings_type.h"
#include "clear_func.h"
#include "window_type.h"
#include "window_func.h"
#include "sound_type.h"
#include "sound_func.h"
#include "tilehighlight_type.h"
#include "tilehighlight_func.h"
#include "company_func.h"
#include "tile_type.h"
#include "rail_type.h"
#include "rail_gui.h"
#include "sprite.h"
#include "fios.h"
#include "copy_paste.h"
#include "table/sprites.h"
#include "table/strings.h"


/** Current railtype. Used for autoconversion */
static RailType _last_railtype = RAILTYPE_RAIL;

/* **** GUI Code for Copy&Paste **** */

/** Enum referring to the widgets of the copy paste window */
enum CopyPasteWidgets {
	CPW_CLOSEBOX = 0,
	CPW_CAPTION,
	CPW_STICKYBOX,
	CPW_SPACER_1,
	CPW_SPACER_2,
	CPW_SPACER_3,
	CPW_COPY,
	CPW_PASTE,
	CPW_LOAD,
	CPW_SAVE,
	CPW_ROTATE_LEFT,
	CPW_ROTATE_RIGHT,
	CPW_MIRROR_HORIZONTAL,
	CPW_MIRROR_VERTICAL,
	CPW_TERRAIN,
	CPW_DYNAMITE,
	CPW_RAIL,
	CPW_ROAD,
	CPW_REVERSE_SIGNALS,
	CPW_CONVERT_RAILTYPE,
	CPW_ONLY_OWN,

	CPW_FIRST_CLICKABLE = CPW_COPY,
	CPW_LAST_CLICKABLE = CPW_ONLY_OWN,
};

struct CopyPasteWindow : Window {
int last_user_action; ///< Last started user action.
public:
	CopyPasteWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
	{
		this->InitNested(desc, window_number);
		this->last_user_action = WIDGET_LIST_END;

		/* Set the button states according to variable content */
		if (_copy_paste.m_clear_before_build) this->LowerWidget(CPW_DYNAMITE);
		if (_copy_paste.m_toggle_signal_direction) this->LowerWidget(CPW_REVERSE_SIGNALS);
		if (_copy_paste.m_convert_rail)	  this->LowerWidget(CPW_CONVERT_RAILTYPE);
		if (_copy_paste.m_copy_with_rail) this->LowerWidget(CPW_RAIL);
		if (_copy_paste.m_copy_with_road) this->LowerWidget(CPW_ROAD);
		if (_copy_paste.m_copy_with_other)this->LowerWidget(CPW_ONLY_OWN);
	}

	virtual void OnPaint()
	{
		SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
				CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
				WIDGET_LIST_END);
		/* Set image for tri-state button */
		this->GetWidget<NWidgetCore>(CPW_TERRAIN)->widget_data = SPR_IMG_MINUS_TERRAIN + _copy_paste.m_paste_vacant_terrain;

		this->DrawWidgets();

		/* Draw CylinderGuy in CompanyColor, if unclicked */
		if (!this->IsWidgetLowered(CPW_ONLY_OWN))
			DrawSprite(SPR_IMG_ONLY_OWN, COMPANY_SPRITE_COLOUR(_current_company), this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_x + 1, this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_y + 1);
	}

	virtual void OnClick(Point pt, int widget, int click_count)
	{
		SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
				CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
				WIDGET_LIST_END);
		if (this->IsWidgetDisabled(widget)) return;
		if ((widget >= CPW_FIRST_CLICKABLE) && (widget <= CPW_LAST_CLICKABLE)) {
			if (widget != CPW_COPY && widget != CPW_PASTE && 
				widget != CPW_DYNAMITE && widget != CPW_REVERSE_SIGNALS && 
				widget != CPW_RAIL && widget !=  CPW_CONVERT_RAILTYPE && 
				widget != CPW_ROAD && widget != CPW_ONLY_OWN) {
				this->HandleButtonClick(widget);
			}
			SndPlayFx(SND_15_BEEP);
			switch (widget) {
				case CPW_COPY:
					HandlePlacePushButton(this, CPW_COPY, SPR_CURSOR_COPY, HT_RECT);
					this->last_user_action = widget;
					break;

				case CPW_PASTE:
					HandlePlacePushButton(this, CPW_PASTE, SPR_CURSOR_PASTE, HT_PREVIEW);
					this->last_user_action = widget;
					break;

				case CPW_LOAD:
					_copy_paste.m_toggle_signal_direction = false;
					/* fallthrough */

				case CPW_SAVE:
					ShowSaveLoadDialog(widget == CPW_SAVE ? SLD_SAVE_TEMPLATE : SLD_LOAD_TEMPLATE);
					break;

				case CPW_ROTATE_LEFT:
				case CPW_ROTATE_RIGHT:
					if (widget == CPW_ROTATE_LEFT)  _copy_paste.RotateSelectionCCW();
					if (widget == CPW_ROTATE_RIGHT) _copy_paste.RotateSelectionCW();
					break;

				case CPW_MIRROR_HORIZONTAL:
				case CPW_MIRROR_VERTICAL:
					if (widget == CPW_MIRROR_HORIZONTAL) _copy_paste.MirrorSelectionHorizontal();
					if (widget == CPW_MIRROR_VERTICAL)   _copy_paste.MirrorSelectionVertical();
					
					/* Toggle SignalDir */
					this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
					break;

				case CPW_TERRAIN:
					_copy_paste.m_paste_vacant_terrain++;
					if (_copy_paste.m_paste_vacant_terrain > 2) _copy_paste.m_paste_vacant_terrain = 0;
					break;

				case CPW_DYNAMITE: case CPW_REVERSE_SIGNALS:
				case CPW_RAIL: case CPW_CONVERT_RAILTYPE:
				case CPW_ROAD: case CPW_ONLY_OWN: {
					this->SetDirty();
					this->ToggleWidgetLoweredState(widget);
					bool state = IsWidgetLowered(widget);
					switch (widget) {
						case CPW_DYNAMITE:	       _copy_paste.m_clear_before_build = state; break;
						case CPW_RAIL:             _copy_paste.m_copy_with_rail = state; break;
						case CPW_ROAD:             _copy_paste.m_copy_with_road = state; break;
						case CPW_REVERSE_SIGNALS:  _copy_paste.m_toggle_signal_direction = state; break;
						case CPW_CONVERT_RAILTYPE: _copy_paste.m_convert_rail = state; break;
						case CPW_ONLY_OWN:         _copy_paste.m_copy_with_other = state; break;
						default: NOT_REACHED();
					}
				} break;
				default: break;
			}

			/* Set Selection size to Copy size */
			if (this->IsWidgetLowered(CPW_PASTE)) {
				if (_copy_paste.GetWidth() > 0)
					SetTileSelectSize(_copy_paste.GetWidth() - 1, _copy_paste.GetHeight() - 1);
			} else {
				SetTileSelectSize(1, 1);
			}
		}
	}

	virtual void OnPlaceObject(Point pt, TileIndex tile)
	{
		switch (this->last_user_action) { 
			case CPW_COPY:
				VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_COPY_AREA);
				VpSetPlaceSizingLimit(255);
				break;

			case CPW_PASTE:
				_copy_paste.PasteArea(tile);
				break;
		}
	}

	virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
	{
		VpSelectTilesWithMethod(pt.x, pt.y, select_method);
	}

	virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
	{
		if (pt.x != -1) {
			switch (select_proc) {
				case DDSP_COPY_AREA:
					_copy_paste.CopyArea(end_tile, start_tile);
					/* Reset SignalDir */
					if (_copy_paste.m_toggle_signal_direction) this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
					this->SetDirty();
					break;
				default:
					break;
			}
		}
	}

	virtual void OnPlaceObjectAbort()
	{
		/* UnclickWindowButtons "copy" and "paste" */
		this->RaiseWidget(CPW_COPY);
		this->RaiseWidget(CPW_PASTE);

		this->SetDirty();
	}

	virtual void OnTimeout()
	{
		this->RaiseWidget(CPW_LOAD);
		this->RaiseWidget(CPW_SAVE);
		this->RaiseWidget(CPW_ROTATE_LEFT);
		this->RaiseWidget(CPW_ROTATE_RIGHT);
		this->RaiseWidget(CPW_MIRROR_HORIZONTAL);
		this->RaiseWidget(CPW_MIRROR_VERTICAL);
		this->RaiseWidget(CPW_TERRAIN);
		this->SetDirty();
	}

	virtual void OnTick()
	{
		/* If railtype has changed, we need to update our GUI */
		if (_last_railtype != _cur_railtype) {
			const RailtypeInfo *rti = GetRailTypeInfo(_cur_railtype);
			_last_railtype = _cur_railtype;
			this->GetWidget<NWidgetCore>(CPW_CONVERT_RAILTYPE)->widget_data = rti->gui_sprites.convert_rail;
			this->SetDirty();
		}
	}
};

static const NWidgetPart _nested_copy_paste_widgets[] = {
	NWidget(NWID_HORIZONTAL),
		NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
		NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_COPY_PASTE_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
		NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
	EndContainer(),
	NWidget(NWID_HORIZONTAL),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_COPY), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_COPY,              STR_COPY_PASTE_COPY_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_PASTE), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_PASTE,             STR_COPY_PASTE_PASTE_TOOLTIP),

		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),

		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_LOAD), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_LOAD,              STR_COPY_PASTE_LOAD_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_SAVE), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_SAVE,              STR_COPY_PASTE_SAVE_TOOLTIP),

		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),

		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_LEFT), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_LEFT,       STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_RIGHT), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_RIGHT,      STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_HORIZONTAL), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_HORIZONTAL, STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_VERTICAL), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_VERTICAL,   STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP),

		NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),

		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_TERRAIN), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_TERRAIN,     STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP),
		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_DYNAMITE), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_DYNAMITE,    STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP),
		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_RAIL), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_NO_RAIL,           STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP),
		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ROAD), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_NO_ROAD,           STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP),
		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_REVERSE_SIGNALS), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_SIGNAL,      STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP),
		NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_CONVERT_RAILTYPE), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_CONVERT_RAIL,      STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP),
		NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ONLY_OWN), SetMinimalSize(22,22),
								SetFill(0, 1), SetDataTip(SPR_IMG_ONLY_OWN,          STR_COPY_PASTE_ONLY_OWN_TOOLTIP),
	EndContainer(),
};

static const WindowDesc _copy_paste_desc(
	WDP_ALIGN_TOOLBAR, 0, 0,
	WC_COPY_PASTE, WC_SCEN_LAND_GEN,
	WDF_CONSTRUCTION,
	_nested_copy_paste_widgets, lengthof(_nested_copy_paste_widgets)
);

void ShowCopyPasteToolbarGui() // When clicking the button in the terrain generation gui
{
	AllocateWindowDescFront<CopyPasteWindow>(&_copy_paste_desc, 0);
}

void ShowCopyPasteToolbar(int button) // When using a shortcut
{
	Window *w;
	/* don't recreate the window if we're clicking on a button and the window exists. */
	if (button < CPW_FIRST_CLICKABLE || !(w = FindWindowById(WC_COPY_PASTE, 0))) {
		DeleteWindowByClass(WC_COPY_PASTE);
		w = new CopyPasteWindow(&_copy_paste_desc, 0);
	}
	if (w != NULL) w->OnClick(Point(), button, 1);
}
