using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace NovelInterpreter.Instance.Drawer
{
	/// <summary>
	/// StringDrawer用の設定
	/// 主に字送りやフォントの種類など
	/// </summary>
	public class TextDrawer : IDrawer
	{
		/// <summary>
		/// フォントの情報など
		/// </summary>
		public GUIStyle style;

		/// <summary>
		/// 文字送り
		/// </summary>
		public float escapementSpeed;

		/// <summary>
		/// 字送り用時間で経過時間を表す
		/// </summary>
		float escapementTime;

		/// <summary>
		/// 表示する文字
		/// </summary>
		string targetText;

		/// <summary>
		/// 表示する文字
		/// </summary>
		public string TargetText
		{
			get { return this.targetText; }
			set
			{
				this.targetText = value;
				this.currentText = "";
			}
		}

		/// <summary>
		/// 現在表示されている文字
		/// </summary>
		string currentText;

		/// <summary>
		/// 現在表示されている文字
		/// </summary>
		public string CurrentText
		{
			get { return this.currentText; }
			protected set { this.currentText = value; }
		}
		
		void Init(GUIStyle style, string targetText, float escapementSpeed)
		{
			this.targetText = targetText;
			this.escapementTime = 0f;
			this.currentText = "";

			if (style == null) style = new GUIStyle();
			this.style = style;

			// escapementSpeedの設定
			try
			{
				if (escapementSpeed >= 0f)
					this.escapementSpeed = escapementSpeed;
				else
					throw new ArgumentOutOfRangeException("TextDrawer.escapementSpeed", "文字送りの速度が異常です");
			}
			catch (ArgumentOutOfRangeException e)
			{
				NeedOverZero(e);
			}
		}

		/// <summary>
		/// 例外用関数, ゼロ以上が欲しい
		/// </summary>
		/// <param name="e">例外</param>
		void NeedOverZero(ArgumentOutOfRangeException e)
		{
			Debug.LogError(e.Message);
			Debug.LogError("入力された値は0以上でなければなりません：" + e.ParamName);
			Application.Quit();
		}

		/// <summary>
		/// GUIStyleをデフォルトのままで描画する場合のコンストラクタ
		/// </summary>
		/// <param name="targetText">描画したい文字</param>
		/// <param name="escapementSpeed">字送りの速度</param>
		public TextDrawer(string targetText, float escapementSpeed)
		{
			Init(new GUIStyle(), targetText, escapementSpeed);
		}

		/// <summary>
		/// GUIStyleを指定して文字を描画するコンストラクタ
		/// </summary>
		/// <param name="style">文字のスタイル</param>
		/// <param name="targetText">描画したい文字</param>
		/// <param name="escapementSpeed">文字送りの速度</param>
		public TextDrawer(GUIStyle style, string targetText, float escapementSpeed)
		{
			Init(style, targetText, escapementSpeed);
		}

		/// <summary>
		/// 文字の描画を行う
		/// </summary>
		/// <param name="transform">このクラスのインスタンスを所有しているオブジェクトのトランスフォーム</param>
		public void Draw(Transform transform)
		{
			Escapement();	// 字送り

			Rect r = new Rect(
				transform.position.x * Screen.width,
				transform.position.y * Screen.height,
				Screen.width, Screen.height);

			GUI.Label(r, this.currentText, this.style);
		}

		/// <summary>
		/// 字送りのチェック
		/// </summary>
		/// <returns>字送りするかどうか</returns>
		bool EscapementCheck()
		{
			this.escapementTime += Time.deltaTime;
			if (this.escapementTime > this.escapementSpeed)
			{
				this.escapementTime = 0;	// ここで字送り時間をリセット
				return true;
			}
			return false;
		}

		/// <summary>
		/// 字送りの実行
		/// </summary>
		void Escapement()
		{
			if (EscapementCheck())
			{
				// 後端に文字を追加
				if (this.currentText.Length < this.targetText.Length)
					this.currentText += this.targetText[this.currentText.Length];
			}
		}
	}
}
