﻿// (c) Copyright HutongGames, LLC 2010-2016. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
	[ActionCategory(ActionCategory.Input)]
	[Tooltip("Perform a raycast into the 2d scene using screen coordinates and stores the results. Use Ray Distance to set how close the camera must be to pick the 2d object. NOTE: Uses the MainCamera!")]
	public class ScreenPick2d : FsmStateAction
	{
		[Tooltip("A Vector3 screen position. Commonly stored by other actions.")]
		public FsmVector3 screenVector;
		
        [Tooltip ("X position on screen.")]
		public FsmFloat screenX;
		
        [Tooltip ("Y position on screen.")]
		public FsmFloat screenY;
		
        [Tooltip("Are the supplied screen coordinates normalized (0-1), or in pixels.")]
		public FsmBool normalized;

		[UIHint(UIHint.Variable)]
		[Tooltip("Store whether the Screen pick did pick a GameObject")]
		public FsmBool storeDidPickObject;
		
        [UIHint(UIHint.Variable)]
		[Tooltip("Store the picked GameObject")]
		public FsmGameObject storeGameObject;
		
        [UIHint(UIHint.Variable)]
		[Tooltip("Store the picked position in world Space")]
		public FsmVector3 storePoint;
		
        [UIHint(UIHint.Layer)]
		[Tooltip("Pick only from these layers.")]
		public FsmInt[] layerMask;
		
        [Tooltip("Invert the mask, so you pick from all layers except those defined above.")]
		public FsmBool invertMask;
		
        [Tooltip("Repeat every frame.")]
        public bool everyFrame;
		
		public override void Reset()
		{
			screenVector = new FsmVector3 { UseVariable = true };
			screenX = new FsmFloat { UseVariable = true };
			screenY = new FsmFloat { UseVariable = true };
			normalized = false;

			storeDidPickObject = null;
			storeGameObject = null;
			storePoint = null;
			layerMask = new FsmInt[0];
			invertMask = false;
			everyFrame = false;
		}
		
		public override void OnEnter()
		{
			DoScreenPick();
			
			if (!everyFrame)
			{
				Finish();
			}
		}
		
		public override void OnUpdate()
		{
			DoScreenPick();
		}
		
		void DoScreenPick()
		{
			if (Camera.main == null)
			{
				LogError("No MainCamera defined!");
				Finish();
				return;
			}
			
			var rayStart = Vector3.zero;
			
			if (!screenVector.IsNone) rayStart = screenVector.Value;
			if (!screenX.IsNone) rayStart.x = screenX.Value;
			if (!screenY.IsNone) rayStart.y = screenY.Value;
			
			if (normalized.Value)
			{
				rayStart.x *= Screen.width;
				rayStart.y *= Screen.height;
			}
			
			var hitInfo = Physics2D.GetRayIntersection(
				Camera.main.ScreenPointToRay(rayStart), 
				Mathf.Infinity, 
				ActionHelpers.LayerArrayToLayerMask(layerMask, invertMask.Value));
			
			var didPick = hitInfo.collider != null;
			storeDidPickObject.Value = didPick;
			
			if (didPick)
			{
				storeGameObject.Value = hitInfo.collider.gameObject;
				storePoint.Value = hitInfo.point;
			}
			else
			{
				// TODO: not sure if this is the right strategy...
				storeGameObject.Value = null;
				storePoint.Value = Vector3.zero;
			}
			
		}
	}
}