using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace WorldOfPeacecraft
{
	public class MapPanel : Panel
	{
		private const int TileSize = 32;
		private const int EntitySize = 10;
		private IBackend Backend;

		private string ImagesFolder = "textures/";
		private Image BowAndArrow;
		private Image Dragon1;
		private Image Dragon2;
		private Image Dragon3;
		private Image Forest;
		private Image Knight;
		private Image Walkable;
		private Image Water;
		private Image Wall;
		private Image Flowers;
		private Random random = new Random ();
		private int FlowerCounter;

		public MapPanel (IBackend backend)
		{
			SetStyle (ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
			Backend = backend;
			this.PreviewKeyDown += board_KeyPress;
			BowAndArrow = Image.FromFile (ImagesFolder + "bow-and-arrow.png", false);
			Dragon1 = Image.FromFile (ImagesFolder + "dragon1.png");
			Dragon2 = Image.FromFile (ImagesFolder + "dragon2.png");
			Dragon3 = Image.FromFile (ImagesFolder + "dragon3.png");
			Forest = Image.FromFile (ImagesFolder + "forest.png");
			Knight = Image.FromFile (ImagesFolder + "knight.png");
			Walkable = Image.FromFile (ImagesFolder + "walkable.jpg");
			Water = Image.FromFile (ImagesFolder + "water.jpg");
			Wall = Image.FromFile(ImagesFolder + "wall.jpg");
			Flowers = Image.FromFile(ImagesFolder + "flowers.png");
		}

		protected override void OnLayout (LayoutEventArgs levent)
		{
			ITile[,] map = Backend.GetMap ();
			if (map != null) {
				int mapWidth = (map.GetLength(0)) * TileSize;
				int mapHeight = (map.GetLength(1)) * TileSize;
				this.SetClientSizeCore(mapWidth, mapHeight);
			}
			base.OnLayout (levent);
		}

        private void board_KeyPress(object sender, PreviewKeyDownEventArgs e)
        {
            switch (e.KeyCode)
            {
                case Keys.A:
                    this.Backend.moveLeft();
                    break;
                case Keys.D:
                    this.Backend.moveRight();
                    break;
                case Keys.W:
                    this.Backend.moveUp();
                    break;
                case Keys.S:
                    this.Backend.moveDown();
                    break;
            }
        }

		protected override void OnMouseClick (MouseEventArgs e)
		{
			base.OnMouseClick (e);
			int targetX = e.X / TileSize;
			int targetY = e.Y / TileSize;
			Backend.MoveTo (targetX, targetY);
		}

		protected override void OnPaint (PaintEventArgs e)
		{
			Graphics g = e.Graphics;
			lock (Backend) {
				PaintMap (g);
				PaintEntities (g);
			}
		}

		public void PaintMap (Graphics g)
		{
			ITile[,] map = Backend.GetMap ();
			if (map != null) {
				FlowerCounter = 0;
				for (int y = 0; y < map.GetLength(1); y++) {
					for (int x = 0; x < map.GetLength(0); x++) {
						int posx = x * TileSize;
						int posy = y * TileSize;
						PaintTile (g, map [x, y], posx, posy);
					}
				}
			}
			else {
				g.FillRectangle(new SolidBrush(Color.White), this.DisplayRectangle);
			}
		}

		public void PaintTile (Graphics g, ITile tile, int x, int y)
		{
			Image image = null;
			if (tile.IsWater ()) {
				image = Water;
			} else if (tile.IsWall ()) {
				image = Wall;
			} else {
				image = Walkable;
			}
			if (image != null) {
				PaintImage (g, x, y, image);
			} else {
				g.FillRectangle (new SolidBrush (Color.Red), x, y, TileSize, TileSize);
			}
			if (tile.IsForest ()) {
				PaintImage (g, x, y, Forest);
			} else if (tile.IsWalkable()) {
				if (FlowerCounter == 4) {
					PaintImage (g, x, y, Flowers);
					FlowerCounter = 0;
				}
				else {
					FlowerCounter++;
				}
			}
			if (tile.IsHuntable ()) {
				PaintImage (g, x, y, BowAndArrow);
			}
		}
		
		public void PaintEntities (Graphics g)
		{
			IEnumerable<IEntity> dragons = Backend.GetDragons ();
			IEnumerable<IEntity> players = Backend.GetPlayers ();
			foreach (IEntity dragon in dragons) {
				int id = dragon.GetId();
				Image image;
				switch (Math.Abs(id % 3))
				{
				case 0:
					image = Dragon1;
					break;
				case 1:
					image = Dragon2;
					break;
				case 2:
					image = Dragon3;
					break;
				default:
					throw new Exception("There is no image for dragon id '" + id + "' (this should never happen)");
				}
				PaintImage(g, dragon.GetX() * TileSize, dragon.GetY() * TileSize, image);
			}
			foreach (IEntity player in players) {
				PaintImage(g, player.GetX() * TileSize, player.GetY () * TileSize, Knight);
			}
		}

		public void PaintImage (Graphics g, int posx, int posy, Image image)
		{
			int x = posx + (TileSize - image.Width) / 2;
			int y = posy + (TileSize - image.Height) / 2;
			g.DrawImage(image, x, y, image.Width, image.Height);
		}

		public void PaintEntity (Graphics g, IPositionable entity, Color color)
		{

		}
	}
}

