/* $Id: command_queue.h 4998 2006-05-30 16:13:41Z Frostregen $ */

#ifndef COPY_PASTE_H
#define COPY_PASTE_H

#include "map_type.h"
#include "command_type.h"
#include "signal_type.h"
#include "track_type.h"
#include "slope_type.h"
#include "road_map.h"
#include "saveload/saveload.h"

class CopyPaste {
public:
	bool  m_copy_with_rail;          ///< If rail should be copied
	bool  m_copy_with_road;          ///< If road should be copied
	bool  m_copy_with_other;         ///< If stuff owned by other players should be copied

	uint8 m_paste_vacant_terrain;    ///< If empty terrain should be recreated. 0 = no terraform, 1 = terraform only needed, 2 = terraform all terrain
	bool  m_convert_rail;            ///< If rails should be converted to currently selected railtype
	bool  m_clear_before_build;      ///< If terrain should be bulldozed before we try to paste it
	bool  m_toggle_signal_direction; ///< If signal direction should be toggled when pasting

private:
	uint32   m_width;
	uint32   m_height;
        StringID error_str;
	char     *error_msg;

	CommandCost m_costs; ///< Stores the costs needed for template paste - estimate

	/** Storage space for copied area 
	 * TODO: Convert to struct (saveload...)
	 */
	int8   *m_heightmap;      ///<  | Move terrain needed into this...
	uint8  *m_terrain_needed; ///<  2Bit needed
	uint8  *m_tiletype;       ///<  8Bit needed
	uint8  *m_railroad;       ///<  8Bit needed
	uint16 *m_signals;        ///< 15Bit needed
	//TODO: uint8 *m_station;

public:
	enum CopyPasteTileType {
		CP_TILE_CLEAR,
		CP_TILE_RAIL,
		CP_TILE_ROAD,
		CP_TILE_TUNNELBRIDGE,
		CP_TILE_STATION,
	};
	explicit CopyPaste();
	~CopyPaste();

	SaveOrLoadResult SaveLoadTemplate(const char *filename, int mode);
	const char *GetErrorString();
	bool IsSomethingCopied(); ///< Returns if something is in our copy buffer.
	void AllocateMapArray(uint32 max_tiles); ///< allocate a map array
	void ClearCopyArrays();   ///< Clears content of copy buffers for current width/height, but does NOT reset width/height.

	void CopyArea(TileIndex end, TileIndex start); ///< Copies given area into copy buffer
	void PasteArea(TileIndex tile);                ///< Paste copied content onto map, taking care of multiplayer/singleplayer environment.

	void RotateSelectionCCW();
	void RotateSelectionCW();
	void MirrorSelectionHorizontal();
	void MirrorSelectionVertical();
	uint GetHeight(uint baseh, uint index);
	Slope GetSlope(uint index);
	CopyPasteTileType GetCPTileType(uint index);
	uint GetCPMinorTileType(uint index);
	TrackBits GetCPTrackBits(uint index);

	FORCEINLINE uint32 GetWidth()  { return m_width;  };	///< Used by the GUI
	FORCEINLINE uint32 GetHeight() { return m_height; };

private:
	void SetError(StringID message, StringID extra = INVALID_STRING_ID);

	void internal_PasteArea(TileIndex tile); ///< internal PasteArea method

	void CP_DoCommand(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd); ///< Special DoCommand for CopyPaste

	void CP_RaiseLowerLand  (TileIndex tile, int mode);
	void CP_PlaceRail       (TileIndex tile, int cmd, uint32 railtype);
	void CP_PlaceSignals    (TileIndex tile, Track track, SignalType type, uint direction, bool semaphore);
	void CP_PlaceRoad       (TileIndex tile, uint8 road_bits);
	void CP_PlaceRoadStop(TileIndex tile, uint8 direction, uint8 roadtype, bool truck_stop, bool drive_through);
	void CP_PlaceRail_Tunnel(TileIndex tile, uint32 railtype);
	void CP_PlaceRoad_Tunnel(TileIndex tile, uint8 roadtype);
	void CP_Build_Bridge    (TileIndex start, TileIndex end, uint8 bridgetype, uint8 transport_type, uint8 rail_road_type);
	void CP_PlaceRail_Depot (TileIndex tile, uint8 railtype, uint8 direction);
	void CP_PlaceRoad_Depot (TileIndex tile, uint8 direction_type);
	void CP_PlaceWaypoint   (TileIndex tile, uint8 waypoint_type);
	void CP_ClearTile       (TileIndex start_tile, TileIndex end_tile);
		
	uint8 MirrorSignalDirection(uint8 direction);
	DisallowedRoadDirections MirrorOneWayRoadDirection(DisallowedRoadDirections drd);
	void SwapSignalInfo(uint index);
	void PasteSignals(uint index, TileIndex tile);
	void PasteLandscape(TileIndex tile);

	void TerrainNeededAroundTile(TileIndex tindex, TileIndex bindex);
	int8 ClampToRight(TileIndex index, int8 baseh, int8 h_tile);
	int8 ClampToUp(TileIndex index, int8 baseh, int8 h_tile, int32 size_x);

	FORCEINLINE void SetWidth(uint32 width)   { m_width  = width;  };
	FORCEINLINE void SetHeight(uint32 height) { m_height = height; }; 
};

extern CopyPaste _copy_paste;

#endif /* COPY_PASTE_H */

