/*
 * +================================================================================+
 *      __  ___  ______________  __  __  ______________   ____
 *     / / / / |/ /  _/_  __/\ \/ / / / / /_  __/  _/ /  / __/
 *    / /_/ /    // /  / /    \  / / /_/ / / / _/ // /___\ \
 *    \____/_/|_/___/ /_/     /_/  \____/ /_/ /___/____/___/
 *
 * +================================================================================+
 *
 *    "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:
 *    David Krummenacher (dave@timbookedtwo.com)
 *
 */

using UnityEngine;

namespace Utils.Behaviours {

	/// <summary>
	/// Exhibition reset. This behavior will load a specified level when no input was received during a given amount of time.
	/// The behavior can be blocked with the blocked flag (eg. in the menu or during cutscenes).
	/// </summary>
	public class ExhibitionReset : MonoBehaviour {

		[Tooltip("The amount of time the game needs to be idle before it resets.")]
		/// <summary>
		/// The amount of time the game needs to be idle before it resets.
		/// </summary>
		public float TimeForReset = 180f;
		[Tooltip("The level to load on reseting.")]
		/// <summary>
		/// The level to load on reseting.
		/// </summary>
		public int LevelToLoad = 0;
		[Tooltip("Determines if the reset is blocked or not. Use this to not restart inside the menu, cutscenes or other scenes/states.")]
		/// <summary>
		/// Determines if the reset is blocked or not.
		/// Use this to not restart inside the menu, cutscenes or other scenes/states.
		/// </summary>
		public bool Blocked = false;

		/// <summary>
		/// The current time.
		/// </summary>
		private float currentTime;

		/// <summary>
		/// Reference to the instance (singleton implementation).
		/// </summary>
		private static ExhibitionReset instance;
		/// <summary>
		/// Gets the instance of this behaviour.
		/// </summary>
		/// <value>The instance.</value>
		public static ExhibitionReset Instance {
			get {
				// Singleton implementation
				if (instance == null) {
						instance = GameObject.FindObjectOfType<ExhibitionReset>();
						
						if (instance == null) {
							GameObject go = new GameObject("ExhibitionReset");
							go.AddComponent<ExhibitionReset>();
						}
						
						DontDestroyOnLoad(instance.gameObject);
				}
					
				return instance;
			}
		}

		void Awake() {
			// Singleton implementation
			if (instance == null) {
				instance = this;
				DontDestroyOnLoad(this);
			}
			else {
				if(this != instance) Destroy(this.gameObject);
			}
		}

		void Start() {
			// Error handling
			if (LevelToLoad < 0) {
				Debug.LogWarning("ExhibitionReset: Level with index " + LevelToLoad + " doesn't exist. Level to load is set to first level.");
				LevelToLoad = 0;
			}
			if (LevelToLoad >= Application.levelCount) {
				Debug.LogWarning("ExhibitionReset: Level with index " + LevelToLoad + " doesn't exist. Level to load is set to last level.");
				LevelToLoad = Application.levelCount - 1;
			}
			if (TimeForReset <= 0f) {
				Debug.LogWarning("ExhibitionReset: Time is lower or equal to 0. This results in instant reloading and probably isn't the desired behavior.");
			}
			
			// Intitialize current time
			currentTime = 0f;
		}

		void Update() {
			// Don't do anything if blocked
			if (Blocked) return;

			// Reset time if input is received otherwise increment current time
			if (Input.anyKey) currentTime = 0f;
			else currentTime += Time.deltaTime;

			// Load level if time ran out
			if (currentTime >= TimeForReset) Application.LoadLevel(LevelToLoad);
		}
	}
}
