using System;
using UnityEngine;

namespace Cryville.Crtr {
	public class SpriteFrame {
#pragma warning disable IDE1006
		Rect _frame;
		public Rect frame {
			get { return _frame; }
			set { _frame = value; }
		}
		public Rect textureRect {
			get { return _frame; }
			set { _frame = value; }
		}

		bool _rotated = false;
		public bool rotated {
			get { return _rotated; }
			set { _rotated = value; }
		}
		public bool textureRotated {
			get { return _rotated; }
			set { _rotated = value; }
		}
#pragma warning restore IDE1006

		public Vector2 offset;

		public Rect sourceColorRect;
		public Vector2 sourceSize;
		private Rect _uv;
		private Vector2[] cuv;
		public Rect UV {
			get {
				return _uv;
			}
			private set {
				_uv = value;
				float x0 = Mathf.Min(_uv.xMin, _uv.xMax);
				float x1 = Mathf.Max(_uv.xMin, _uv.xMax);
				float y0 = Mathf.Min(_uv.yMin, _uv.yMax);
				float y1 = Mathf.Max(_uv.yMin, _uv.yMax);
				if (_rotated) cuv = new Vector2[]{
						new Vector2(x0, y1),
						new Vector2(x1, y0),
						new Vector2(x0, y0),
						new Vector2(x1, y1),
					};
				else cuv = new Vector2[]{
						new Vector2(x0, y0),
						new Vector2(x1, y1),
						new Vector2(x1, y0),
						new Vector2(x0, y1),
					};
			}
		}
		public Vector2 GetUV(Vector2 uv) {
			return GetUV(uv.x, uv.y);
		}
		public Vector2 GetUV(float u, float v) {
			Vector2 uv00 = cuv[0], uv11 = cuv[1],
				uv10 = cuv[2], uv01 = cuv[3];
			return (1 - u - v) * uv00
				+ u * uv10
				+ v * uv01
				+ u * v * (uv00 + uv11 - uv10 - uv01);
		}
		public Texture2D Texture {
			get;
			private set;
		}
		public Vector2 Size {
			get {
				return new Vector2(Texture.width, Texture.height);
			}
		}

		public void Init() {
			if (Texture == null)
				throw new InvalidOperationException("Missing texture");
			_frame = new Rect(Vector2.zero, Size);
			var w = _frame.width;
			var h = _frame.height;
			float x = _frame.x / w;
			float y = 1 - _frame.y / h;
			float tw = (_rotated ? _frame.height : _frame.width) / w;
			float th = (_rotated ? _frame.width : _frame.height) / h;
			if (_rotated) UV = new Rect(x, y, tw, -th);
			else UV = new Rect(x, y, tw, -th);
		}

		public void Init(int w, int h, Texture2D _base) {
			if (Texture != null)
				throw new InvalidOperationException("Missing texture");
			Texture = _base;
			float x = _frame.x / w;
			float y = 1 - _frame.y / h;
			float tw = (_rotated ? _frame.height : _frame.width) / w;
			float th = (_rotated ? _frame.width : _frame.height) / h;
			if (_rotated) UV = new Rect(x, y, tw, -th);
			else UV = new Rect(x, y, tw, -th);
		}
		public SpriteFrame() { }
		public SpriteFrame(Texture2D tex) {
			Texture = tex;
		}
	}
}
