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

namespace Nostalgia.Example
{
	[AddComponentMenu("Nostalgia/Example/StageManager"), RequireComponent(typeof(AudioSource))]
	public sealed class StageManager : MonoBehaviour
	{
		static StageManager _Instance;
		static StageManager instance
		{
			get
			{
				return _Instance;
			}
		}
		public Stage currentStage;
		public Player player;
		public CameraController cameraController;
		public Image screenFade;

		private AudioSource _AudioSource;
		private Stage currentStagePrefab;
		private int currentPos = -1;

		void Awake()
		{
			if (QualitySettings.antiAliasing != 0)
			{
				Debug.LogWarning("Nostalgia.Example.StateManager: Tilemaps has tearing between tiles because anti-aliasing is enabled.\nDisabled anti-aliasing.");
				QualitySettings.antiAliasing = 0;
			}

			_Instance = this;

			_AudioSource = GetComponent<AudioSource>();

			cameraController.Initialize(currentStage);
		}

		void Start()
		{
		}

		void OnEnable()
		{
			screenFade.gameObject.SetActive(true);
			screenFade.CrossFadeAlpha(0.0f, 0.0f, true);
		}

		IEnumerator WaitFade(float alpha, float volume, float duration)
		{
			screenFade.CrossFadeAlpha(alpha, duration, true);

			float preVolume = _AudioSource.volume;

			float time = Time.unscaledTime;
			while (Time.unscaledTime - time < duration)
			{
				float t = Mathf.Clamp01((Time.unscaledTime - time) / duration);
				_AudioSource.volume = Mathf.Lerp(preVolume, volume, t);
				yield return null;
			}

			_AudioSource.volume = volume;
		}

		public void BeginGame()
		{
			if (currentStage == null)
			{
				return;
			}

			_AudioSource.clip = currentStage.bgm;
			_AudioSource.loop = true;
			_AudioSource.Play();
		}

		IEnumerator ChangeStageCoroutine(Stage stage, int pos)
		{
			Time.timeScale = 0.0f;

			yield return StartCoroutine(WaitFade(1.0f, 0.0f, 1.0f));

			if (currentStage != null)
			{
				_AudioSource.Stop();
				_AudioSource.clip = null;
				Destroy(currentStage.gameObject);
				currentStage = null;
				player.ClearGround();

				InfoBoard.Close();
			}

			currentStagePrefab = stage;

			if (stage != null)
			{
				currentStage = Instantiate(stage);
				currentStage.transform.SetParent(transform);
				Transform playerPos = 0 <= pos && pos < currentStage.doors.Count ? currentStage.doors[pos] : null;
				if (playerPos != null)
				{
					Vector3 position = playerPos.position;
					position.y -= 0.5f;
					player.transform.position = position;
				}

				cameraController.Initialize(currentStage);
				_AudioSource.clip = currentStage.bgm;
				_AudioSource.loop = true;
				_AudioSource.Play();
			}

			yield return StartCoroutine(WaitFade(0.0f, 0.1f, 1.0f));

			Time.timeScale = 1.0f;
		}

		void ChangeStageInternal(Stage stage, int pos)
		{
			if (currentStagePrefab == stage && currentPos == pos)
			{
				return;
			}

			StartCoroutine(ChangeStageCoroutine(stage, pos));
		}

		public static void ChangeStage(Stage stage, int pos)
		{
			_Instance.ChangeStageInternal(stage, pos);
		}

		void ChangeBGMInternal(AudioClip clip, bool loop)
		{
			_AudioSource.clip = clip;
			_AudioSource.loop = loop;
			_AudioSource.Play();
		}

		public static void ChangeBGM(AudioClip clip, bool loop)
		{
			_Instance.ChangeBGMInternal(clip, loop);
		}
	}
}
