using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using PunkMan.Shared;


namespace PunkMan.Editor
{
	/// <summary>
	/// Summary description for Main.
	/// </summary>
	public class MainForm : System.Windows.Forms.Form
	{
		private System.Windows.Forms.MainMenu mainMenu;
		private System.Windows.Forms.MenuItem menuItem1;
		private System.Windows.Forms.MenuItem menuItem2;
		private System.Windows.Forms.MenuItem menuItem3;
		private System.Windows.Forms.MenuItem menuItem4;
		private System.Windows.Forms.MenuItem menuItem5;
		private System.Windows.Forms.MenuItem menuItem6;
		private System.Windows.Forms.MenuItem menuItem7;
		private System.Windows.Forms.MenuItem menuItem8;
		private System.Windows.Forms.ImageList toolBarImageList;
		private System.Windows.Forms.ToolBar toolBar;
		private System.Windows.Forms.GroupBox entityGroupBox;
		private System.Windows.Forms.ListView textureView;
		private System.Windows.Forms.ImageList textureList;
		private System.Windows.Forms.OpenFileDialog openFileDialog;
		private System.Windows.Forms.SaveFileDialog saveFileDialog;
		private System.Windows.Forms.ToolBarButton tbbTextureMode;
		private System.Windows.Forms.ToolBarButton tbbEntityMode;
		private System.Windows.Forms.Panel mapArea;
		private System.Windows.Forms.PictureBox mapBox;
		private System.Windows.Forms.Panel toolPanel;
		private System.Windows.Forms.ListBox entityList;
		private System.Windows.Forms.ToolBarButton tbbWalkable;
		private System.Windows.Forms.ToolBarButton tbbSeparator1;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.MenuItem menuItem9;
		private System.Windows.Forms.MenuItem menuItem10;
		private System.Windows.Forms.MenuItem menuItem11;

		private NewForm newFileDialog;

		/// <summary>
		/// Common constructor.
		/// </summary>
		public MainForm()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			newFileDialog = new NewForm();
			
			Size mapSize = new Size(10 * gridWidth, 10 * gridHeight);
			mapBox.Size = mapSize;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(MainForm));
			this.mainMenu = new System.Windows.Forms.MainMenu();
			this.menuItem1 = new System.Windows.Forms.MenuItem();
			this.menuItem2 = new System.Windows.Forms.MenuItem();
			this.menuItem4 = new System.Windows.Forms.MenuItem();
			this.menuItem3 = new System.Windows.Forms.MenuItem();
			this.menuItem5 = new System.Windows.Forms.MenuItem();
			this.menuItem6 = new System.Windows.Forms.MenuItem();
			this.menuItem7 = new System.Windows.Forms.MenuItem();
			this.menuItem8 = new System.Windows.Forms.MenuItem();
			this.toolBar = new System.Windows.Forms.ToolBar();
			this.tbbTextureMode = new System.Windows.Forms.ToolBarButton();
			this.tbbEntityMode = new System.Windows.Forms.ToolBarButton();
			this.tbbSeparator1 = new System.Windows.Forms.ToolBarButton();
			this.tbbWalkable = new System.Windows.Forms.ToolBarButton();
			this.toolBarImageList = new System.Windows.Forms.ImageList(this.components);
			this.toolPanel = new System.Windows.Forms.Panel();
			this.textureView = new System.Windows.Forms.ListView();
			this.textureList = new System.Windows.Forms.ImageList(this.components);
			this.entityGroupBox = new System.Windows.Forms.GroupBox();
			this.entityList = new System.Windows.Forms.ListBox();
			this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
			this.mapArea = new System.Windows.Forms.Panel();
			this.mapBox = new System.Windows.Forms.PictureBox();
			this.menuItem9 = new System.Windows.Forms.MenuItem();
			this.menuItem10 = new System.Windows.Forms.MenuItem();
			this.menuItem11 = new System.Windows.Forms.MenuItem();
			this.toolPanel.SuspendLayout();
			this.entityGroupBox.SuspendLayout();
			this.mapArea.SuspendLayout();
			this.SuspendLayout();
			// 
			// mainMenu
			// 
			this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					 this.menuItem1,
																					 this.menuItem9});
			// 
			// menuItem1
			// 
			this.menuItem1.Index = 0;
			this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem2,
																					  this.menuItem4,
																					  this.menuItem3,
																					  this.menuItem5,
																					  this.menuItem6,
																					  this.menuItem7,
																					  this.menuItem8});
			this.menuItem1.Text = "&File";
			// 
			// menuItem2
			// 
			this.menuItem2.Index = 0;
			this.menuItem2.Shortcut = System.Windows.Forms.Shortcut.CtrlN;
			this.menuItem2.Text = "&New...";
			this.menuItem2.Click += new System.EventHandler(this.menuItem2_Click);
			// 
			// menuItem4
			// 
			this.menuItem4.Index = 1;
			this.menuItem4.Shortcut = System.Windows.Forms.Shortcut.CtrlO;
			this.menuItem4.Text = "&Open...";
			this.menuItem4.Click += new System.EventHandler(this.menuItem4_Click);
			// 
			// menuItem3
			// 
			this.menuItem3.Index = 2;
			this.menuItem3.Text = "-";
			// 
			// menuItem5
			// 
			this.menuItem5.Index = 3;
			this.menuItem5.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
			this.menuItem5.Text = "&Save";
			this.menuItem5.Click += new System.EventHandler(this.menuItem5_Click);
			// 
			// menuItem6
			// 
			this.menuItem6.Index = 4;
			this.menuItem6.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftS;
			this.menuItem6.Text = "Save &as...";
			this.menuItem6.Click += new System.EventHandler(this.menuItem6_Click);
			// 
			// menuItem7
			// 
			this.menuItem7.Index = 5;
			this.menuItem7.Text = "-";
			// 
			// menuItem8
			// 
			this.menuItem8.Index = 6;
			this.menuItem8.Shortcut = System.Windows.Forms.Shortcut.CtrlQ;
			this.menuItem8.Text = "E&xit";
			this.menuItem8.Click += new System.EventHandler(this.menuItem8_Click);
			// 
			// toolBar
			// 
			this.toolBar.Appearance = System.Windows.Forms.ToolBarAppearance.Flat;
			this.toolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] {
																					   this.tbbTextureMode,
																					   this.tbbEntityMode,
																					   this.tbbSeparator1,
																					   this.tbbWalkable});
			this.toolBar.Dock = System.Windows.Forms.DockStyle.Bottom;
			this.toolBar.DropDownArrows = true;
			this.toolBar.ImageList = this.toolBarImageList;
			this.toolBar.Location = new System.Drawing.Point(0, 399);
			this.toolBar.Name = "toolBar";
			this.toolBar.ShowToolTips = true;
			this.toolBar.Size = new System.Drawing.Size(592, 42);
			this.toolBar.TabIndex = 0;
			this.toolBar.ButtonClick += new System.Windows.Forms.ToolBarButtonClickEventHandler(this.toolBar_ButtonClick);
			// 
			// tbbTextureMode
			// 
			this.tbbTextureMode.ImageIndex = 0;
			this.tbbTextureMode.Pushed = true;
			this.tbbTextureMode.Style = System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
			this.tbbTextureMode.Text = "Texture mode";
			this.tbbTextureMode.ToolTipText = "Push this button to switch to set entities for map cells.";
			// 
			// tbbEntityMode
			// 
			this.tbbEntityMode.ImageIndex = 1;
			this.tbbEntityMode.Style = System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
			this.tbbEntityMode.Text = "Entity mode";
			this.tbbEntityMode.ToolTipText = "Push this button to set textures for map cells.";
			// 
			// tbbSeparator1
			// 
			this.tbbSeparator1.Style = System.Windows.Forms.ToolBarButtonStyle.Separator;
			// 
			// tbbWalkable
			// 
			this.tbbWalkable.ImageIndex = 2;
			this.tbbWalkable.Style = System.Windows.Forms.ToolBarButtonStyle.ToggleButton;
			this.tbbWalkable.Text = "Walkable";
			// 
			// toolBarImageList
			// 
			this.toolBarImageList.ImageSize = new System.Drawing.Size(16, 16);
			this.toolBarImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("toolBarImageList.ImageStream")));
			this.toolBarImageList.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// toolPanel
			// 
			this.toolPanel.BackColor = System.Drawing.SystemColors.Control;
			this.toolPanel.Controls.Add(this.textureView);
			this.toolPanel.Controls.Add(this.entityGroupBox);
			this.toolPanel.Dock = System.Windows.Forms.DockStyle.Right;
			this.toolPanel.Location = new System.Drawing.Point(412, 0);
			this.toolPanel.Name = "toolPanel";
			this.toolPanel.Size = new System.Drawing.Size(180, 399);
			this.toolPanel.TabIndex = 1;
			// 
			// textureView
			// 
			this.textureView.BackColor = System.Drawing.SystemColors.ControlDark;
			this.textureView.Dock = System.Windows.Forms.DockStyle.Fill;
			this.textureView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
			this.textureView.HideSelection = false;
			this.textureView.LargeImageList = this.textureList;
			this.textureView.Location = new System.Drawing.Point(0, 0);
			this.textureView.MultiSelect = false;
			this.textureView.Name = "textureView";
			this.textureView.Size = new System.Drawing.Size(180, 295);
			this.textureView.TabIndex = 1;
			this.textureView.SelectedIndexChanged += new System.EventHandler(this.textureView_SelectedIndexChanged);
			// 
			// textureList
			// 
			this.textureList.ImageSize = new System.Drawing.Size(128, 128);
			this.textureList.TransparentColor = System.Drawing.Color.Transparent;
			// 
			// entityGroupBox
			// 
			this.entityGroupBox.Controls.Add(this.entityList);
			this.entityGroupBox.Dock = System.Windows.Forms.DockStyle.Bottom;
			this.entityGroupBox.Location = new System.Drawing.Point(0, 295);
			this.entityGroupBox.Name = "entityGroupBox";
			this.entityGroupBox.Size = new System.Drawing.Size(180, 104);
			this.entityGroupBox.TabIndex = 0;
			this.entityGroupBox.TabStop = false;
			this.entityGroupBox.Text = "Entity";
			// 
			// entityList
			// 
			this.entityList.Dock = System.Windows.Forms.DockStyle.Fill;
			this.entityList.Items.AddRange(new object[] {
															"[none]",
															"Player start",
															"Player end",
															"Monster",
															"Rum",
															"Absinth"});
			this.entityList.Location = new System.Drawing.Point(3, 16);
			this.entityList.Name = "entityList";
			this.entityList.Size = new System.Drawing.Size(174, 82);
			this.entityList.TabIndex = 0;
			this.entityList.SelectedIndexChanged += new System.EventHandler(this.entityList_SelectedIndexChanged);
			// 
			// openFileDialog
			// 
			this.openFileDialog.Filter = "PunkMan game XML map|*.xml|All files|*.*";
			// 
			// saveFileDialog
			// 
			this.saveFileDialog.Filter = "PunkMan game XML map|*.xml|All files|*.*";
			// 
			// mapArea
			// 
			this.mapArea.AutoScroll = true;
			this.mapArea.BackColor = System.Drawing.SystemColors.ControlDark;
			this.mapArea.Controls.Add(this.mapBox);
			this.mapArea.Dock = System.Windows.Forms.DockStyle.Fill;
			this.mapArea.Location = new System.Drawing.Point(0, 0);
			this.mapArea.Name = "mapArea";
			this.mapArea.Size = new System.Drawing.Size(412, 399);
			this.mapArea.TabIndex = 2;
			// 
			// mapBox
			// 
			this.mapBox.BackColor = System.Drawing.SystemColors.ControlDark;
			this.mapBox.Location = new System.Drawing.Point(0, 0);
			this.mapBox.Name = "mapBox";
			this.mapBox.Size = new System.Drawing.Size(456, 455);
			this.mapBox.TabIndex = 4;
			this.mapBox.TabStop = false;
			this.mapBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.mapBox_MouseDown);
			// 
			// menuItem9
			// 
			this.menuItem9.Index = 1;
			this.menuItem9.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
																					  this.menuItem10,
																					  this.menuItem11});
			this.menuItem9.Text = "&View";
			// 
			// menuItem10
			// 
			this.menuItem10.Checked = true;
			this.menuItem10.Index = 0;
			this.menuItem10.Text = "Show &walkable mark";
			this.menuItem10.Click += new System.EventHandler(this.menuItem10_Click);
			// 
			// menuItem11
			// 
			this.menuItem11.Checked = true;
			this.menuItem11.Index = 1;
			this.menuItem11.Text = "Show &entities";
			this.menuItem11.Click += new System.EventHandler(this.menuItem11_Click);
			// 
			// MainForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(592, 441);
			this.Controls.Add(this.mapArea);
			this.Controls.Add(this.toolPanel);
			this.Controls.Add(this.toolBar);
			this.Menu = this.mainMenu;
			this.MinimumSize = new System.Drawing.Size(300, 300);
			this.Name = "MainForm";
			this.Text = "PunkMan X1 Editor";
			this.Closing += new System.ComponentModel.CancelEventHandler(this.MainForm_Closing);
			this.Load += new System.EventHandler(this.MainForm_Load);
			this.toolPanel.ResumeLayout(false);
			this.entityGroupBox.ResumeLayout(false);
			this.mapArea.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// Editor entry point.
		/// </summary>
		/// <param name="args">Command line arguments</param>
		public static void Main(string[] args)
		{
			Application.Run(new MainForm());
		}

		/// <summary>
		/// Main form load event handler.
		/// </summary>
		/// <param name="sender">event sender</param>
		/// <param name="e">event arguments</param>
		private void MainForm_Load(object sender, System.EventArgs e)
		{
			try
			{
				LoadTextures(GetDataFilePath("textures"));
			}
			catch
			{
				MessageBox.Show(this, "It seems to not found directory with textures. This may be caused by using editor out of game directory structure. Please, put the application exe file into right place (bin directory in game directory) and rerun it.");
				Close();
			}
		}

		//--------------------[ here goes my code ]--------------------

		/// <summary>
		/// Mode of editor
		/// </summary>
		private enum EditorMode
		{
			/// <summary>
			/// This mode is for editing of map cell attributes like texture or walkable. 
			/// </summary>
			Texture, 
			/// <summary>
			/// This mode is for editing of map cell entity attribute.
			/// </summary>
			Entity
		}

		/// <summary>
		/// Mode of editor
		/// </summary>
		private EditorMode editorMode;

		/// <summary>
		/// Selected entity type
		/// </summary>
		private MapCell.EntityType selectedEntity = MapCell.EntityType.None;

		/// <summary>
		/// Is selected walkable. Reflects tbbWalkable push state.
		/// </summary>
		private bool settingWalkable = false;


		/// <summary>
		/// This indicates whater walkable map cell attribute is shown.
		/// </summary>
		private bool visSpace = true;
		/// <summary>
		/// This indicates whater map cell entity is shown.
		/// </summary>
		private bool visEntities = true;

		/// <summary>
		/// The edited map.
		/// </summary>
		private Map map = new Map(10,10);

		/// <summary>
		/// The bitmap representation of edited map.
		/// </summary>
		private Bitmap mapBitmap = null;

		/// <summary>
		/// Path of edited file. If the file path is not known this is empty ("") string.
		/// </summary>
		private string fileName = "";

		/// <summary>
		/// Indicates whater is edited file modified.
		/// </summary>
		private bool modified = false;


		/// <summary>
		/// Array of bitmap of possible map cell textures.
		/// </summary>
		private Bitmap[] smallTextureList;

		/// <summary>
		/// Index of selected texture.
		/// </summary>
		private int textureNo = 0;

		/// <summary>
		/// Grid width constant
		/// </summary>
		private readonly int gridWidth = 32;
		/// <summary>
		/// Grid height constant
		/// </summary>
		private readonly int gridHeight = 32;


		/// <summary>
		/// Retrun path to data directory
		/// 
		/// </summary>
		/// <param name="name">repository name</param>
		/// <returns>Path to file / directory</returns>
		private static string GetDataFilePath(string name)
		{
			string exePath = Application.StartupPath;
			// check for data path
			// standard path
			string dataPath1 = exePath + @"\..\data";
			// build path
			string dataPath2 = exePath + @"\..\..\..\data";
			// editor build path
			string dataPath3 = exePath + @"\..\..\..\..\data";
			if (Directory.Exists(dataPath1)) return dataPath1 + "\\" + name;
			if (Directory.Exists(dataPath2)) return dataPath2 + "\\" + name;
			else return dataPath3 + "\\" + name;
		}


		/// <summary>
		/// This method loades textures from game data directory.
		/// </summary>
		/// <param name="path">The path of texture directory</param>
		private void LoadTextures(string path)
		{
			textureList.Images.Clear();
			StreamReader reader = new StreamReader(new FileStream(path + @"\texture.list", FileMode.Open));

			int i = 0;
			Size size = new Size(gridWidth, gridHeight);
			while (reader.Peek() > 0)
			{
				string fullName = path +@"\"+ reader.ReadLine();
                
				if (!File.Exists(fullName)) continue;

				Bitmap tex = new Bitmap(fullName, false);
                


				textureList.Images.Add(tex);

				string si = i.ToString();
				ListViewItem item = new ListViewItem(si, i);
				
				textureView.Items.Add(item);
				i++;

			}
			smallTextureList = new Bitmap[textureList.Images.Count];
			for (i = 0; i < textureList.Images.Count; i++)
			{

				smallTextureList[i] = new Bitmap(textureList.Images[i], gridWidth, gridHeight);
			}

			mapBitmap = new Bitmap(map.DataWidth * gridWidth, map.DataHeight * gridHeight);
			mapBox.Image = mapBitmap;
			RedrawMapBitmap();
			mapBox.Invalidate();
		}


		/// <summary>
		/// Redraws whole bitmap of map layout. (Updates mapBitmap field.)
		/// </summary>
		private void RedrawMapBitmap()
		{
			for (int x = 0; x < map.DataWidth; x++)
				for (int y = 0; y < map.DataHeight; y++)
					RedrawMapBitmap(x, y);

		}


		/// <summary>
		/// Entity list selected index changed event handler ;)
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void entityList_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			MapCell.EntityType[] trans = new MapCell.EntityType[]
				{ 
					MapCell.EntityType.None, MapCell.EntityType.Start, MapCell.EntityType.End,
					MapCell.EntityType.Monster, MapCell.EntityType.Rum, MapCell.EntityType.Absinth
				};
			selectedEntity = trans[entityList.SelectedIndex];
		}

		/// <summary>
		/// Toolbar click event handler
		/// </summary>
		/// <param name="sender">Event sender</param>
		/// <param name="e">Arguments of event</param>
		private void toolBar_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e)
		{
			if (e.Button == tbbTextureMode)
			{
				tbbEntityMode.Pushed = false;
				//tbbTextureMode.Pushed = true;
				editorMode = EditorMode.Texture;
			}
			else if (e.Button == tbbEntityMode)
			{
				tbbTextureMode.Pushed = false;
				//tbbEntityMode.Pushed = true;
				editorMode = EditorMode.Entity;
					
			}
			else if (e.Button == tbbWalkable)
			{
				//tbbWalkable.Pushed
				settingWalkable = tbbWalkable.Pushed;
			}
		}


		

		/// <summary>
		/// Texture view selected index changed event handler ;)
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void textureView_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			if (textureView.SelectedIndices.Count == 0) return;
			textureNo = textureView.SelectedIndices[0];
		}

		/// <summary>
		/// Map box mouse down event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void mapBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			modified = true;
			Point p = mapArea.AutoScrollPosition;
			int x = e.X - mapBox.Location.X + p.X;
			int y = e.Y - mapBox.Location.Y + p.Y;
			int mx = x / gridWidth;
			int my = y / gridHeight;
            
			if (mx >= map.DataWidth || my >= map.DataHeight || mx < 0 || my < 0)
				return;

			Point fp = Map.EmptyPoint;
			switch(editorMode)
			{
				case EditorMode.Entity:
					if (selectedEntity == MapCell.EntityType.Start)
					{
						fp = map.FindStartPoint();
						if (p != Map.EmptyPoint)
						{
							map.Data[fp.X, fp.Y].Entity = MapCell.EntityType.None;
						}
					}
					else if (selectedEntity == MapCell.EntityType.End)
					{
						fp = map.FindEndPoint();
						if (p != Map.EmptyPoint)
						{
							map.Data[fp.X, fp.Y].Entity = MapCell.EntityType.None;
						}
					}
					map.Data[mx,my].Entity = selectedEntity;

					RedrawMapBitmap(mx,my);
					if (fp != Map.EmptyPoint)
						RedrawMapBitmap(fp.X, fp.Y);
					mapBox.Invalidate();
					break;

				case EditorMode.Texture:
					map.Data[mx,my].Index = textureNo;
					map.Data[mx,my].Walkable = settingWalkable;
					RedrawMapBitmap(mx,my);
					mapBox.Invalidate();
					break;
			}
			


		}

		

		/// <summary>
		/// This method redraws map cell (Updates mapBitmap field)
		/// </summary>
		/// <param name="x">x position of cell in map </param>
		/// <param name="y">x position of cell in map </param>
		private void RedrawMapBitmap(int x, int y)
		{
            
			System.Drawing.Font fnt = new System.Drawing.Font(FontFamily.GenericMonospace, 14f);
			//if (x < 0 || x >= map.DataWidth || y < 0 || y >= map.DataHeight) 
			//    return;
			int rx = x * gridWidth;
			int ry = y * gridHeight;
			Graphics g = Graphics.FromImage(mapBitmap);
			g.DrawImage(smallTextureList[map.Data[x, y].Index], rx, ry);
			g.DrawLine(Pens.Black, rx + gridWidth - 1, ry, rx + gridWidth - 1, ry + gridHeight - 1);
			g.DrawLine(Pens.Black, rx, ry + gridHeight - 1, rx + gridWidth, ry + gridHeight - 1);
			if (visSpace && map.Data[x, y].Walkable)
			{
				g.DrawLine(Pens.OrangeRed, rx, ry, rx + gridWidth, ry + gridHeight);
				g.DrawLine(Pens.OrangeRed, rx + gridWidth, ry, rx, ry + gridHeight);

			}
			if (visEntities && map.Data[x, y].Entity != MapCell.EntityType.None)
			{
				switch (map.Data[x, y].Entity)
				{
					case MapCell.EntityType.Start:
						g.DrawString("St", fnt, Brushes.Pink, rx, ry);
						break;

					case MapCell.EntityType.End:
						g.DrawString("Ed", fnt, Brushes.Pink, rx, ry);
						break;

					case MapCell.EntityType.Monster:
						g.DrawString("Mt", fnt, Brushes.Pink, rx, ry);
						break;

					case MapCell.EntityType.Rum:
						g.DrawString("R", fnt, Brushes.Pink, rx, ry);
						break;

					case MapCell.EntityType.Absinth:
						g.DrawString("A", fnt, Brushes.Red, rx, ry);
						break;

				}
			}
			g.Dispose();
		}

		/// <summary>
		/// Validate map integrity. Checks if cells where is placed a entity is walkable.
		/// </summary>
		/// <param name="err">Consequnce of error description</param>
		/// <returns>True if map is OK.</returns>
		private bool ValidateMap(out string err)
		{
			err = "";
			Point p = map.FindStartPoint();
			if (p == Map.EmptyPoint)
			{
				err = "There is no start point in map.";
				return false;
			}

			if (!map.Data[p.X, p.Y].Walkable)
			{
				err = "The start point is not walkable.";
				return false;
			}
			

			p = map.FindEndPoint();
			if (p == Map.EmptyPoint)
			{
				err = "There is no end point in map.";
				return false;
			}

			if (!map.Data[p.X, p.Y].Walkable)
			{
				err = "The end point is not walkable.";
				return false;
			}
			

			for (int x = 0; x < map.DataWidth; x++)
			{
				for (int y = 0; y < map.DataHeight; y++)
				{
					if (map.Data[x,y].Entity != MapCell.EntityType.None && !map.Data[x,y].Walkable)
					{
						err = "At position (" + x.ToString() + "," + y.ToString() + ") is entity but this position is not walkable."; 
						return false;
					}
				}
			}

			return true;



		}

		/// <summary>
		/// Asks for size of new map and creats it.
		/// </summary>
		private void NewMap()
		{
			if (newFileDialog.ShowDialog() == DialogResult.OK)
			{
				map = new Map(newFileDialog.MapWidth, newFileDialog.MapHeight);
				fileName = "";
				modified = false;
			}

		}

		/// <summary>
		/// Asks for path of file to load and loads it.
		/// </summary>
		private void LoadMap()
		{
			if (openFileDialog.ShowDialog() == DialogResult.OK)
			{
				fileName = openFileDialog.FileName;
				try
				{
					map.LoadXML(fileName);
				}
				catch (Map.FormatException e)
				{
					MessageBox.Show(this,e.Message,"Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
					return;
				}
				modified = false;
			}
		}

		/// <summary>
		/// If theres no specified file name, asks for file path and saves it.
		/// </summary>
		/// <returns>Was file saved successfuly?</returns>
		private bool SaveMap()
		{
			string err;
			if (!ValidateMap(out err))
			{
				err += " File was not saved. Please fix it.";
				MessageBox.Show(this, err);
				return false;
			}
			if (fileName.CompareTo("") == 0)
			{
				if (saveFileDialog.ShowDialog() == DialogResult.OK)
				{
					fileName = saveFileDialog.FileName;
				}
				else return false;
			}

			map.SaveXML(fileName);
			modified = false;
			return true;
		}

		/// <summary>
		/// Asks for file path and saves the map.
		/// </summary>
		/// <returns>Was file saved successfuly?</returns>
		private bool SaveAsMap()
		{
			string err;
			if (!ValidateMap(out err))
			{
				err += " File was not saved. Please fix it.";
				MessageBox.Show(this, err);
				return false;
			}
			if (saveFileDialog.ShowDialog() == DialogResult.OK)
			{
				fileName = saveFileDialog.FileName;
			}
			else return false;
		
			map.SaveXML(fileName);
			modified = false;
			return true;
		}

		/// <summary>
		/// "New" file menu item click event handler
		/// </summary>
		/// <param name="sender">Seneder of event</param>
		/// <param name="e">Event arguments</param>
		private void menuItem2_Click(object sender, System.EventArgs e)
		{
			if (modified)
			{
				if (MessageBox.Show(this, "Map was modified without saving. Do you want save changes?", "Question",
					MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				{
					if (!SaveMap()) return;
				}
			}
			NewMap();
			RedrawMapBitmap();
			mapBox.Invalidate();

		}

		/// <summary>
		/// "Open" file menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void menuItem4_Click(object sender, System.EventArgs e)
		{
			if (modified)
			{
				if (MessageBox.Show(this, "Map was modified without saving. Do you want save changes?", "Question",
					MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
				{
					if (!SaveMap()) return;
				}
			}
			LoadMap();
			RedrawMapBitmap();
			mapBox.Invalidate();

		}

		/// <summary>
		/// "Save" file menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void menuItem5_Click(object sender, System.EventArgs e)
		{
			SaveMap();
		}

		/// <summary>
		/// "Save as" file menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void menuItem6_Click(object sender, System.EventArgs e)
		{
			SaveAsMap();
		}

		/// <summary>
		/// "Exit" file menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event argumetns</param>
		private void menuItem8_Click(object sender, System.EventArgs e)
		{
			Close();
		}

		/// <summary>
		/// Application closing event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if (modified)
			{
				switch(MessageBox.Show(this, "Your map was modified but not saved. Would you save it before exit?", 
					"Question", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
				{
					case DialogResult.Yes:
						if (!SaveMap()) e.Cancel = true;
						break;

					case DialogResult.Cancel:
						e.Cancel = true;
						break;
				}
			}		
		}

		/// <summary>
		/// "Show walkable mark" view menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Evenet arguments</param>
		private void menuItem10_Click(object sender, System.EventArgs e)
		{
			menuItem10.Checked = ! menuItem10.Checked;
			visSpace = menuItem10.Checked;
			RedrawMapBitmap();
			mapBox.Invalidate();
		}

		/// <summary>
		/// "Show entities" view menu item click event handler
		/// </summary>
		/// <param name="sender">Sender of event</param>
		/// <param name="e">Event arguments</param>
		private void menuItem11_Click(object sender, System.EventArgs e)
		{
			menuItem11.Checked = ! menuItem11.Checked;
			visEntities = menuItem11.Checked;
			RedrawMapBitmap();
			mapBox.Invalidate();
		}

	}
}
