/*
 * +================================================================================+
 *      __  ___  ______________  __  __  ______________   ____
 *     / / / / |/ /  _/_  __/\ \/ / / / / /_  __/  _/ /  / __/
 *    / /_/ /    // /  / /    \  / / /_/ / / / _/ // /___\ \
 *    \____/_/|_/___/ /_/     /_/  \____/ /_/ /___/____/___/
 *
 * +================================================================================+
 *
 *    "THE BEER-WARE LICENSE"
 *    -----------------------
 *
 *    As long as you retain this notice you can do whatever you want with this
 *    stuff. However it is expressly forbidden to sell or commercially distribute
 *    Unity Utils or parts of it apart from your games.
 *    If you meet any of the authors some day, and you think this stuff is
 *    worth it, you can buy them a beer in return.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *    THE SOFTWARE.
 *
 * +================================================================================+
 *
 *    Authors:
 *    Michael Müller (mik@mikmueller.ch)
 *
 */

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;

namespace Utils.UI {

	/// <summary>
	/// HoldInput checks wether a boolean is true for a given time and fires an event (OnHoldInputActivated).
	/// </summary>
	public class HoldInput : MonoBehaviour {

		/// <summary>
		/// Occurs when on hold input activated.
		/// </summary>
		public delegate void AcivatedHoldInput(object sender);

		/// <summary>
		/// Occurs when on hold input activated.
		/// </summary>
		public event AcivatedHoldInput OnHoldInputActivated;

		/// <summary>
		/// The input boolean. Input.GetKey(KeyCode.Space) for example.
		/// </summary>
		public bool Active;

		/// <summary>
		/// The time to activate the button, in seconds.
		/// </summary>
		public float TimeToActivate;

		/// <summary>
		/// The hold-input elapsed time.
		/// </summary>
		private float holdInputTime = 0;

		/// <summary>
		/// Indicates if the event was fired or not.
		/// </summary>
		private bool fired;

		/// <summary>
		/// The Button action that should be executed when button got activated
		/// </summary>
		void Action() {
			if (!fired) {
				fired = true;
				OnHoldInputActivated (this);
			}
	 	}

		// Update is called once per frame
		void Update () {
			if (Active) {
				HoldButton ();
			} else {
				ResetInputTime();
				fired = false;
			}
			UpdateRepresentation ();
		}

		/// <summary>
		/// Increases the button-time.
		/// </summary>
		void HoldButton() {
			if (holdInputTime < TimeToActivate) {
					holdInputTime += Time.deltaTime;
			} else {
				Action ();
			} 
		}

		/// <summary>
		/// Resets the input time.
		/// </summary>
		void ResetInputTime() {
			holdInputTime = 0;
		}

		/// <summary>
		/// Updates the representation.
		/// </summary>
		void UpdateRepresentation() {
			if (GetComponent<Renderer> () != null) {
				GetComponent<Renderer> ().material.SetFloat ("_Cutoff", Mathf.InverseLerp (TimeToActivate, 0, holdInputTime));
			} else if (GetComponent<Image> ()) {
				GetComponent<Image> ().material.SetFloat ("_Cutoff", Mathf.InverseLerp (TimeToActivate, 0, holdInputTime));
			} else {
				Debug.LogError("No Renderer or UI.Image attached to gameobject.");
			}
		}

	}

}

