//----------------------------------------------//
// Gamelogic Grids                              //
// http://www.gamelogic.co.za                   //
// Copyright (c) 2014 Gamelogic (Pty) Ltd       //
//----------------------------------------------//

using Gamelogic.Grids;
using UnityEngine;

public enum ImageMapMode
{
	Stretch,
	StretchWidth,
	StrethcHeight
}

/**
	Map that maps a grid to an image; useful for texturing a grid with a single image, or 
	point an image with a grid.
*/
[Experimental]
public class UVImageMap<TPoint> 
	where TPoint : IGridPoint<TPoint>
{
	private readonly IMap<TPoint> map;
	private Rect imageRect;
	private Vector2 anchorPoint;
	private Vector2 ratio;

	public UVImageMap(IGridSpace<TPoint> grid, IMap<TPoint> map, ImageMapMode mode)
	{
		imageRect = new Rect(0, 0, 1, 1);
		this.map = map;
		
		Vector2 gridDimensions = map.CalcGridDimensions(grid);
		anchorPoint = map.CalcAnchorBottomLeft(grid);

		if (mode == ImageMapMode.StretchWidth)
		{
			var yOffset = (gridDimensions.x - gridDimensions.y)/2;
			anchorPoint.y = anchorPoint.y - yOffset;
		}
		else if (mode == ImageMapMode.StrethcHeight)
		{
			var xOffset = (gridDimensions.y - gridDimensions.x) / 2;
			anchorPoint.x = anchorPoint.x - xOffset;
		}

		ratio.x = mode == ImageMapMode.StrethcHeight
			? gridDimensions.y/imageRect.height
			: gridDimensions.x/imageRect.width;

		ratio.y = mode == ImageMapMode.StretchWidth 
			? gridDimensions.x/imageRect.width
			: gridDimensions.y / imageRect.height;
	}

	public Vector2 this[TPoint point]
	{
		get
		{
			var worldPoint = map[point];

			var x = (worldPoint.x - anchorPoint.x) / ratio.x + imageRect.xMin;
			var y = (worldPoint.y - anchorPoint.y) / ratio.y + imageRect.yMin;

			return new Vector2(x, y);
		}
	}

	public TPoint this[Vector2 point]
	{
		get
		{
			var x = (point.x - imageRect.xMin) / ratio.x + anchorPoint.x;
			var y = (point.y - imageRect.yMin) / ratio.y + anchorPoint.y;

			var worldPoint = new Vector2(x, y);

			return map[worldPoint];
		}
	}

	public Vector2 GetCellDimensions(TPoint point)
	{
		var cellDimensions = map.GetCellDimensions(point);
		var x = cellDimensions.x / ratio.x;
		var y = cellDimensions.y / ratio.y;

		return new Vector2(x, y);
	}

	public Vector2 GetCellScale(TPoint point)
	{
		var cellDimensions = GetCellDimensions(point);

		return new Vector2(1f / cellDimensions.x, 1f / cellDimensions.y);
	}
}
