using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Library2D;

namespace GraveyardGraph
{
	public class TileWall : Drawable
	{
		public const float HALF_PI = (float) Math.PI / 2f;
		public const float HORIZ_DEPTH = 0.2f;
		public const float VERT_DEPTH = 0.4f;

		public Vector2 Center
		{
			get { return new Vector2(_center.X, _center.Y); }
			set { _center = value; }
		}
		private Vector2 _center = Vector2.Zero;

		public enum TileGraphic { TCap, BCap, I, L, T, X };
		public TileGraphic Tile {
			get { return _tile; }
			set { _tile = value; }
		}
		private TileGraphic _tile;

		private int neighborCase;

		public TileWall(Vector2 center, char above, char below, char left, char right)
		{
			_center = center;
			CalculateGraphics(above, below, left, right);
		}

		public void Draw(SpriteBatch sb)
		{
			/* Draw arguments:
		 	 * Texture2D texture,
			 * Vector2 Position,
			 * nullable<Rectangle> sourceRec,
			 * Color color,
			 * float rotation,
			 * Vector2 origin,
			 * float scale,
			 * SpriteEffects effects,
			 * float layerDepth
			 */
			List<Texture2D> tileTextures = new List<Texture2D>();
			List<int> rotations = new List<int>();
			List<float> depth = new List<float>();
			switch (Tile)
			{
				case TileGraphic.I:
					{
						tileTextures.Add(ArtFetcher.SeaweedI);
						if (neighborCase == 6)
						{
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
						}
						else {
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
						}
							
						break;
					}
				case TileGraphic.TCap:
				case TileGraphic.BCap:
				case TileGraphic.L:
					{
						if ((neighborCase & 8) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedBCap);
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
						}
						if ((neighborCase & 4) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedTCap);
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
						}
						if ((neighborCase & 2) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedBCap);
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
						}
						if ((neighborCase & 1) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedTCap);
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
						}
						break;
					}
				case TileGraphic.T:
					{
						tileTextures.Add(ArtFetcher.SeaweedI);
						int remainingCase = neighborCase;
						if ((neighborCase & 6) == 6)
						{
							//both left and right are present
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
							remainingCase -= 6;
						}
						else {
							//must be both top and bottom
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
							remainingCase -= 9;
						}

						if ((remainingCase & 8) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedBCap);
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
						}
						if ((remainingCase & 4) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedTCap);
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
						}
						if ((remainingCase & 2) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedBCap);
							rotations.Add(1);
							depth.Add(HORIZ_DEPTH);
						}
						if ((remainingCase & 1) > 0)
						{
							tileTextures.Add(ArtFetcher.SeaweedTCap);
							rotations.Add(0);
							depth.Add(VERT_DEPTH);
						}
						break;
					}
				case TileGraphic.X:
					{
						tileTextures.Add(ArtFetcher.SeaweedI);
						rotations.Add(0);
						depth.Add(VERT_DEPTH);
						tileTextures.Add(ArtFetcher.SeaweedI);
						rotations.Add(1);
						depth.Add(HORIZ_DEPTH);
						break;
					}
			}
			for (int i = 0; i < tileTextures.Count; i++)
			{
				sb.Draw(
					tileTextures[i],
					new Rectangle((int)Center.X, (int)Center.Y, Game1.TILE_SIZE, Game1.TILE_SIZE),
					null,
					Color.White,
					rotations[i] * HALF_PI,
					new Vector2(Game1.TILE_SIZE / 2),
					SpriteEffects.None,
					depth[i]
				);
			}
		}

		//The following arrays specify which cases map to which arts and/or rotations. See chart below:
		// 8
		//4#2
		// 1
		public static readonly int[] tcapNeighborCase = { 1, 2 };
		public static readonly int[] bcapNeighborCase = { 4, 8 };
		public static readonly int[] lNeighborCase = { 3, 5, 10, 12 };
		public static readonly int[] iNeighborCase = { 6, 9 };
		public static readonly int[] tNeighborCase = { 7, 11, 13, 14 };
		public static readonly int[] xNeighborCase = { 15 };

		public void CalculateGraphics(char above, char below, char left, char right)
		{
			//Calculate what case we're looking at
			// 8
			//4#2
			// 1
			neighborCase = 0;
			if (above == '#')
			{
				neighborCase += 8;
			}
			if (left == '#')
			{
				neighborCase += 4;
			}
			if (right == '#')
			{
				neighborCase += 2;
			}
			if (below == '#')
			{
				neighborCase += 1;
			}

			//Figure out which case we're in for the texture
			if (Array.IndexOf(tcapNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.TCap;
			}
			else if (Array.IndexOf(bcapNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.BCap;
			}
			else if (Array.IndexOf(lNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.L;
			}
			else if (Array.IndexOf(iNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.I;
			}
			else if (Array.IndexOf(tNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.T;
			}
			else if (Array.IndexOf(xNeighborCase, neighborCase) != -1)
			{
				Tile = TileGraphic.X;
			}
		}
	}
}

