﻿using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace AC.Downloads.IsometricCamera
{

#if UNITY_EDITOR

	[CustomEditor (typeof (GameCameraIso))]
	public class GameCameraIsoEditor : Editor
	{

		public override void OnInspectorGUI ()
		{
			GameCameraIso _target = (GameCameraIso) target;
			_target.ShowGUI ();

			if (GUI.changed)
			{
				EditorUtility.SetDirty (_target);
			}
		}

	}

#endif


	public class GameCameraIso : CursorInfluenceCamera
	{

		#region Variables

		[SerializeField] private float dampSpeed = 0.9f;
		[SerializeField] private bool limitX = false;
		[SerializeField] private bool limitZ = false;
		[SerializeField] private Vector2 xLimits;
		[SerializeField] private Vector2 zLimits;
		[SerializeField] private Vector3 offset = new Vector3 (6f, 8f, 10f);

		private const float offsetChangeSpeed = 2f;
		private Vector3 actualOffset;
		private LerpUtils.Vector3Lerp positionLerp = new LerpUtils.Vector3Lerp ();
		private LerpUtils.Vector3Lerp offsetLerp = new LerpUtils.Vector3Lerp ();

		#endregion


		#region UnityStandards

		protected override void Start ()
		{
			base.Start ();

			ResetTarget ();

			if (target)
			{
				SetTargetOriginalPosition ();
				MoveCameraInstant ();
			}
		}


		public override void _Update ()
		{
			transform.position = positionLerp.Update (transform.position, GetTargetPosition (), dampSpeed);

			actualOffset = offsetLerp.Update (actualOffset, offset, offsetChangeSpeed);
		}

		#endregion


		#region PublicFunctions

		public void SetOffset (Vector3 newOffset, bool isInstant)
		{
			offset = newOffset;

			if (isInstant)
			{
				actualOffset = newOffset;
			}
		}


		public override void MoveCameraInstant ()
		{
			if (target == null)
			{
				Start ();
			}
			transform.position = GetTargetPosition ();
		}

		#endregion


		#region PrivateFunctions

		private void SetTargetOriginalPosition ()
		{
			actualOffset = offset;
		}


		private Vector3 GetTargetPosition ()
		{
			Vector3 position = target.position + offset;
			if (limitX)
			{
				position.x = Mathf.Clamp (position.x, xLimits.x, xLimits.y);
			}
			if (limitZ)
			{
				position.z = Mathf.Clamp (position.z, zLimits.x, zLimits.y);
			}
			return position;
		}

		#endregion


#if UNITY_EDITOR

		public void ShowGUI ()
		{
			ShowCursorInfluenceGUI ();
			EditorGUILayout.Space ();

			EditorGUILayout.BeginVertical ("Button");
			EditorGUILayout.LabelField ("Constraints", EditorStyles.boldLabel);
			limitX = EditorGUILayout.Toggle ("Limit X?", limitX);
			if (limitX)
			{
				xLimits[0] = EditorGUILayout.FloatField ("Min X:", xLimits[0]);
				xLimits[1] = EditorGUILayout.FloatField ("Max X:", xLimits[1]);
			}
			limitZ = EditorGUILayout.Toggle ("Limit Z?", limitZ);
			if (limitZ)
			{
				zLimits[0] = EditorGUILayout.FloatField ("Min Z:", zLimits[0]);
				zLimits[1] = EditorGUILayout.FloatField ("Max Z:", zLimits[1]);
			}
			EditorGUILayout.EndVertical ();
			EditorGUILayout.Space ();

			EditorGUILayout.BeginVertical ("Button");
			EditorGUILayout.LabelField ("Target object", EditorStyles.boldLabel);

			targetIsPlayer = CustomGUILayout.Toggle ("Target is Player?", targetIsPlayer, "", "If True, the camera will follow the active Player");

			if (!targetIsPlayer)
			{
				target = (Transform) CustomGUILayout.ObjectField<Transform> ("Target:", target, true, string.Empty, "The object for the camera to follow");
			}

			offset = CustomGUILayout.Vector3Field ("Offset:", offset);
			dampSpeed = CustomGUILayout.FloatField ("Follow speed:", dampSpeed, "", "The follow speed when tracking a target");
			EditorGUILayout.EndVertical ();
		}

#endif


		#region GetSet

		public override bool CursorOffsetForcesTranslation
		{
			get
			{
				return true;
			}
		}

		#endregion

	}

}