// This file can be included several times.

#ifndef REGISTER_QUICK_ACTION
// This helps IDEs properly syntax highlight the uses of the macro below.
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description)
#endif

#define ALWAYS_FALSE []() -> bool { return false; }
#define DEFAULT_BTN []() -> int { return -1; }

REGISTER_QUICK_ACTION(
	ShowHelp,
	"Show help",
	[&]() { ShowHelp(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[F1] Open the DDNet Wiki page for the map editor in a web browser.")
REGISTER_QUICK_ACTION(
	Exit,
	"Exit",
	[&]() { Exit(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Escape] Exit from the editor.")
REGISTER_QUICK_ACTION(
	BrushPicker,
	"Brush picker",
	[&]() { m_ShowPickerToggle = !m_ShowPickerToggle; },
	[&]() -> bool {
		return m_Mode != MODE_LAYERS ||
		       Map()->m_vSelectedLayers.size() != 1 ||
		       Map()->SelectedLayer(0) == nullptr ||
		       (Map()->SelectedLayer(0)->m_Type != LAYERTYPE_TILES && Map()->SelectedLayer(0)->m_Type != LAYERTYPE_QUADS);
	},
	[&]() -> bool { return m_ShowPickerToggle; },
	DEFAULT_BTN,
	"[Ctrl+Space, Hold Space] Toggle brush picker.")
REGISTER_QUICK_ACTION(
	ToggleGrid,
	"Toggle grid",
	[&]() { MapView()->MapGrid()->Toggle(); },
	ALWAYS_FALSE,
	[&]() -> bool { return MapView()->MapGrid()->IsEnabled(); },
	DEFAULT_BTN,
	"[Ctrl+G] Toggle grid.")
REGISTER_QUICK_ACTION(
	GameTilesAir,
	"Game tiles: Air",
	[&]() { FillGameTiles(EGameTileOp::AIR); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesHookable,
	"Game tiles: Hookable",
	[&]() { FillGameTiles(EGameTileOp::HOOKABLE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesDeath,
	"Game tiles: Death",
	[&]() { FillGameTiles(EGameTileOp::DEATH); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesUnhookable,
	"Game tiles: Unhookable",
	[&]() { FillGameTiles(EGameTileOp::UNHOOKABLE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesHookthrough,
	"Game tiles: Hookthrough",
	[&]() { FillGameTiles(EGameTileOp::HOOKTHROUGH); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesFreeze,
	"Game tiles: Freeze",
	[&]() { FillGameTiles(EGameTileOp::FREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesUnfreeze,
	"Game tiles: Unfreeze",
	[&]() { FillGameTiles(EGameTileOp::UNFREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesDeepFreeze,
	"Game tiles: Deep Freeze",
	[&]() { FillGameTiles(EGameTileOp::DEEP_FREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesDeepUnfreeze,
	"Game tiles: Deep Unfreeze",
	[&]() { FillGameTiles(EGameTileOp::DEEP_UNFREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesBlueCheckTele,
	"Game tiles: Blue Check Tele",
	[&]() { FillGameTiles(EGameTileOp::BLUE_CHECK_TELE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesRedCheckTele,
	"Game tiles: Red Check Tele",
	[&]() { FillGameTiles(EGameTileOp::RED_CHECK_TELE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesLiveFreeze,
	"Game tiles: Live Freeze",
	[&]() { FillGameTiles(EGameTileOp::LIVE_FREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	GameTilesLiveUnfreeze,
	"Game tiles: Live Unfreeze",
	[&]() { FillGameTiles(EGameTileOp::LIVE_UNFREEZE); },
	[&]() -> bool { return !CanFillGameTiles(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Construct game tiles from this layer.")
REGISTER_QUICK_ACTION(
	AddGroup,
	"Add group",
	[&]() { AddGroup(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Add a new group.")
REGISTER_QUICK_ACTION(
	ResetZoom,
	"Reset zoom",
	[&]() { MapView()->ResetZoom(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Numpad*] Zoom to normal and remove editor offset.")
REGISTER_QUICK_ACTION(
	ZoomOut,
	"Zoom out",
	[&]() { MapView()->Zoom()->ScaleValue(1.331f); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Numpad-] Zoom out.")
REGISTER_QUICK_ACTION(
	ZoomIn,
	"Zoom in",
	[&]() { MapView()->Zoom()->ScaleValue(1.0f / 1.331f); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Numpad+] Zoom in.")
REGISTER_QUICK_ACTION(
	Refocus,
	"Refocus",
	[&]() { MapView()->Focus(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Home] Restore map focus.")
REGISTER_QUICK_ACTION(
	GotoPosition,
	"Goto position",
	[&]() { GotoPosition(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Go to a specified coordinate point on the map.")
REGISTER_QUICK_ACTION(
	Proof,
	"Proof",
	[&]() { MapView()->ProofMode()->Toggle(); },
	ALWAYS_FALSE,
	[&]() -> bool { return MapView()->ProofMode()->IsEnabled(); },
	DEFAULT_BTN,
	"Toggle proof borders. These borders represent the area that a player can see with default zoom.")
REGISTER_QUICK_ACTION(
	AddTileLayer, "Add tile layer", [&]() { AddTileLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new tile layer.")
REGISTER_QUICK_ACTION(
	AddSwitchLayer,
	"Add switch layer",
	[&]() { AddSwitchLayer(); },
	[&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pSwitchLayer; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Create a new switch layer.")
REGISTER_QUICK_ACTION(
	AddTuneLayer,
	"Add tune layer",
	[&]() { AddTuneLayer(); },
	[&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pTuneLayer; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Create a new tuning layer.")
REGISTER_QUICK_ACTION(
	AddSpeedupLayer,
	"Add speedup layer",
	[&]() { AddSpeedupLayer(); },
	[&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pSpeedupLayer; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Create a new speedup layer.")
REGISTER_QUICK_ACTION(
	AddTeleLayer,
	"Add tele layer",
	[&]() { AddTeleLayer(); },
	[&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pTeleLayer; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Create a new tele layer.")
REGISTER_QUICK_ACTION(
	AddFrontLayer,
	"Add front layer",
	[&]() { AddFrontLayer(); },
	[&]() -> bool { return !Map()->SelectedGroup()->m_GameGroup || Map()->m_pFrontLayer; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Create a new item layer.")
REGISTER_QUICK_ACTION(
	AddQuadsLayer, "Add quads layer", [&]() { AddQuadsLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new quads layer.")
REGISTER_QUICK_ACTION(
	AddSoundLayer, "Add sound layer", [&]() { AddSoundLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Create a new sound layer.")
REGISTER_QUICK_ACTION(
	NewMap,
	"New map",
	[&]() {
		Reset();
		AddDefaultMap();
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+N] Create a new map.")
REGISTER_QUICK_ACTION(
	Save,
	"Save",
	[&]() {
		if(Map()->m_aFilename[0] != '\0' && Map()->m_ValidSaveFilename)
		{
			CallbackSaveMap(Map()->m_aFilename, IStorage::TYPE_SAVE, this);
		}
		else
		{
			m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save", "maps", "", CallbackSaveMap, this);
		}
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+S] Save the current map.")
REGISTER_QUICK_ACTION(
	SaveAs,
	"Save as",
	[&]() {
		m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save as", "maps", Map()->m_aAutosaveName, CallbackSaveMap, this);
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+Shift+S] Save the current map under a new name.")
REGISTER_QUICK_ACTION(
	SaveCopy,
	"Save copy",
	[&]() {
		m_FileBrowser.ShowFileDialog(IStorage::TYPE_SAVE, CFileBrowser::EFileType::MAP, "Save map", "Save copy", "maps", Map()->m_aAutosaveName, CallbackSaveCopyMap, this);
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+Shift+Alt+S] Save a copy of the current map under a new name.")
REGISTER_QUICK_ACTION(
	LoadMap,
	"Load map",
	[&]() {
		m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::MAP, "Load map", "Load", "maps", "", CallbackOpenMap, this);
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+L] Open a map for editing.")
REGISTER_QUICK_ACTION(
	LoadIngameMap,
	"Load ingame map",
	[&]() {
		LoadIngameMap();
	},
	[&]() -> bool { return Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK; },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+Shift+L] Open the current ingame map for editing.")
REGISTER_QUICK_ACTION(
	AppendMap,
	"Append map",
	[&]() {
		m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::MAP, "Append map", "Append", "maps", "", CallbackAppendMap, this);
	},
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+A] Open a map and add everything from that map to the current map.")
REGISTER_QUICK_ACTION(
	CloseMap,
	"Close map",
	[&]() { CloseMap(m_SelectedMap, true); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+F4] Close the current map.")
REGISTER_QUICK_ACTION(
	Envelopes,
	"Envelopes",
	[&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES ? EXTRAEDITOR_NONE : EXTRAEDITOR_ENVELOPES; },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	[&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES; },
	"Toggle the envelope editor.")
REGISTER_QUICK_ACTION(
	ServerSettings,
	"Server settings",
	[&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_SERVER_SETTINGS ? EXTRAEDITOR_NONE : EXTRAEDITOR_SERVER_SETTINGS; },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	[&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_SERVER_SETTINGS; },
	"Toggle the server settings editor.")
REGISTER_QUICK_ACTION(
	History,
	"History",
	[&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_HISTORY ? EXTRAEDITOR_NONE : EXTRAEDITOR_HISTORY; },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	[&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_HISTORY; },
	"Toggle the editor history view.")
REGISTER_QUICK_ACTION(
	AddImage,
	"Add image",
	[&]() { m_FileBrowser.ShowFileDialog(IStorage::TYPE_ALL, CFileBrowser::EFileType::IMAGE, "Add image", "Add", "mapres", "", AddImage, this); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Load a new image to use in the map.")
REGISTER_QUICK_ACTION(
	LayerPropAddImage,
	"Layer: add image",
	[&]() { LayerSelectImage(); },
	[&]() -> bool { return !IsNonGameTileLayerSelected(); },
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Pick mapres image for currently selected layer.")
REGISTER_QUICK_ACTION(
	ShowInfoOff,
	"Show info: Off",
	[&]() {
		m_ShowTileInfo = SHOW_TILE_OFF;
	},
	ALWAYS_FALSE,
	[&]() -> bool { return m_ShowTileInfo == SHOW_TILE_OFF; },
	DEFAULT_BTN,
	"Do not show tile information.")
REGISTER_QUICK_ACTION(
	ShowInfoDec,
	"Show info: Dec",
	[&]() {
		m_ShowTileInfo = SHOW_TILE_DECIMAL;
	},
	ALWAYS_FALSE,
	[&]() -> bool { return m_ShowTileInfo == SHOW_TILE_DECIMAL; },
	DEFAULT_BTN,
	"[Ctrl+I] Show tile information.")
REGISTER_QUICK_ACTION(
	ShowInfoHex,
	"Show info: Hex",
	[&]() {
		m_ShowTileInfo = SHOW_TILE_HEXADECIMAL;
	},
	ALWAYS_FALSE,
	[&]() -> bool { return m_ShowTileInfo == SHOW_TILE_HEXADECIMAL; },
	DEFAULT_BTN,
	"[Ctrl+Shift+I] Show tile information in hexadecimal.")
REGISTER_QUICK_ACTION(
	PreviewQuadEnvelopes,
	"Preview quad envelopes",
	[&]() {
		m_ShowEnvelopePreview = !m_ShowEnvelopePreview;
		m_ActiveEnvelopePreview = EEnvelopePreview::NONE;
	},
	ALWAYS_FALSE,
	[&]() -> bool { return m_ShowEnvelopePreview; },
	DEFAULT_BTN,
	"Toggle previewing the paths of quads with a position envelope when a quad layer is selected.")
REGISTER_QUICK_ACTION(
	DeleteLayer,
	"Delete layer",
	[&]() { DeleteSelectedLayer(); },
	[&]() -> bool {
		std::shared_ptr<CLayer> pCurrentLayer = Map()->SelectedLayer(0);
		if(!pCurrentLayer)
			return true;
		return Map()->m_pGameLayer == pCurrentLayer;
	},
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Delete the layer.")
REGISTER_QUICK_ACTION(
	Pipette,
	"Pipette",
	[&]() { m_ColorPipetteActive = !m_ColorPipetteActive; },
	ALWAYS_FALSE,
	[&]() -> bool { return m_ColorPipetteActive; },
	DEFAULT_BTN,
	"[Ctrl+Shift+C] Color pipette. Pick a color from the screen by clicking on it.")
REGISTER_QUICK_ACTION(
	MapDetails,
	"Map details",
	[&]() { MapDetails(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Adjust the map details of the current map.")
REGISTER_QUICK_ACTION(
	AddQuad,
	"Add quad",
	[&]() { AddQuadOrSound(); },
	[&]() -> bool {
		std::shared_ptr<CLayer> pLayer = Map()->SelectedLayer(0);
		if(!pLayer)
			return false;
		return pLayer->m_Type != LAYERTYPE_QUADS;
	},
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+Q] Add a new quad.")
REGISTER_QUICK_ACTION(
	AddSoundSource,
	"Add sound source",
	[&]() { AddQuadOrSound(); },
	[&]() -> bool {
		std::shared_ptr<CLayer> pLayer = Map()->SelectedLayer(0);
		if(!pLayer)
			return false;
		return pLayer->m_Type != LAYERTYPE_SOUNDS;
	},
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"[Ctrl+Q] Add a new sound source.")
REGISTER_QUICK_ACTION(
	TestMapLocally,
	"Test map locally",
	[&]() { TestMapLocally(); },
	ALWAYS_FALSE,
	ALWAYS_FALSE,
	DEFAULT_BTN,
	"Run a local server with the current map and connect you to it.")

#undef ALWAYS_FALSE
#undef DEFAULT_BTN
