///<reference path="all.ts"/>
module jg {
	/**
	 * メッセージウィンドウを表示するクラス。
	 * UIWindowクラスの継承サンプル、並びにMultilineTextクラスの使用サンプルを兼ねている。
	 */
	export class MessageWindow extends UIWindow {
		/** 次カーソルの表示実態。本フィールドを直接編集しても次カーソルは変わらないため、次カーソルの表示を変更する場合setNextCursorメソッドを利用する */
		_nextCursor: Sprite;
		/** 次カーソルの元画像。これに対してcreateSpriteをしてから次カーソルを描画する。変更する場合setNextCursorメソッドを利用するのを推奨 */
		nextCursor: E;
		/** 現在までのテキスト表示位置 */
		scriptOffset: number;
		/** 表示するテキスト */
		script: string;
		/** テキスト表示速度（通常） */
		normalSpeed: number;
		/** テキスト表示速度（高速） */
		fastSpeed: number;
		/** 表示が完了した場合に発火されるイベント。パラメータがtrueであればまだ未読のスクリプトが次ページ以降に残っている事を示している */
		readed: Trigger;
		/** ページ表示が完了したことを示すフラグ */
		isReaded: boolean;
		/** ページ送りで利用されるクリッピング領域 */
		textClip: Shape;
		/** 次ページがあることを示すカーソルが出ているかどうか */
		hasNextCursor: boolean;
		/** テキスト表示用MultilineText */
		textArea: MultilineText;

		/**
		 * コンストラクタ
		 * @param width 横幅
		 * @param height 縦幅
		 * @param bgImage 背景画像
		 * @param padding 上下左右の余白幅
		 */
		constructor(width:number, height:number, bgImage?:any, padding?:IRectangle) {
			super(width, height, bgImage, padding);

			this.normalSpeed = 400;
			this.fastSpeed = 800;

			this.readed = new Trigger();
			this.isReaded = true;
			this.hasNextCursor = false;

			var textArea = new MultilineText({
				width: this.width-this.padding.left-this.padding.right,
				height: this.height-this.padding.top-this.padding.bottom
			}, {
				x: this.padding.left,
				y: this.padding.top
			});
			this.setTextArea(textArea);

			var cursor = new Line({x:0, y:0}, {x:6, y:8});
			cursor.addLine(12, 0);
			cursor.closePath = true;
			cursor.fill = true;
			cursor.setFillColor("rgba(255, 255, 255, 0.8)");
			cursor.width = 12;
			cursor.height = 8;
			this.nextCursor = cursor;
		}

		/**
		 * MultilineTextを設定する。
		 * 通常、内部的に自動設定されるため、本メソッドを外部から呼び出す必要性は無い
		 */
		setTextArea(textArea:MultilineText) {
			if (this.textArea) {
				this.textArea.remove();
				this.textClip.remove();
			}
			textArea.animated.handle(this, this.onAnimated);
			this.textArea = textArea;
			this.textClip = new Shape(this.width, this.height);
			this.textClip.setClip(true);
			this.textClip.moveTo(textArea.x, textArea.y);
			this.append(this.textClip);
			this.append(textArea);
		}

		/**
		 * 次カーソルを取得
		 */
		getNextCursor():E {
			return this.nextCursor;
		}
		/**
		 * 次カーソルを設定する
		 * @param cursor 設定する次カーソル
		 */
		setNextCursor(cursor:E) {
			this.nextCursor = cursor;
		}

		/**
		 * テキストを設定する
		 * @param text テキスト
		 * @param offset テキストの処理開始オフセット位置
		 */
		setText(text:string, offset?:number):number {
			var textArea = this.textArea;
			this.scriptOffset = textArea.setText(text, offset);
			this.script = textArea.script;
			textArea.hideAll();
			this.deleteNextCursor();
			this.isReaded = false;
			return this.scriptOffset;
		}
		/**
		 * スクリプトを設定する
		 * @param script スクリプト
		 * @param offset スクリプトの処理開始オフセット位置
		 */
		setScript(script:string, offset?:number):number {
			var textArea = this.textArea;
			this.script = script;
			this.scriptOffset = textArea.setScript(script, offset);
			textArea.hideAll();
			this.deleteNextCursor();
			this.isReaded = false;
			return this.scriptOffset;
		}

		/**
		 * 次カーソルを表示する。既に表示されている場合処理を行わない
		 */
		showNextCursor() {
			if (this.hasNextCursor)
				return;
			var nextCursor = this.nextCursor.createSprite();
			var textArea = this.textArea;
			var lastLine = textArea.lines[textArea.lines.length - 1];
			nextCursor.moveTo(
				this.width / 2 - nextCursor.width / 2,
				this.height - nextCursor.height - this.padding.bottom - 4
			);
			nextCursor.tl().moveBy(0, 4, 500).moveBy(0, -4, 500).delay(500).loop();
			this.append(nextCursor);
			this.hasNextCursor = true;
			this._nextCursor = nextCursor;
		}

		/**
		 * 次カーソルを削除する。表示されていない場合処理を行わない
		 */
		deleteNextCursor() {
			if (this.hasNextCursor) {
				this._nextCursor.remove();
				delete this._nextCursor;
				this.hasNextCursor = false;
			}
		}

		/**
		 * 非表示にする
		 * @param fade trueにするとフェードアウトアニメーション後非表示にする
		 */
		hide(fade?:boolean) {
			if (fade)
				this.tl().fadeOut(200);
			else
				super.hide();
		}
		/**
		 * 表示する
		 * @param fade trueにするとファー度インアニメーション後表示する
		 */
		show(fade?:boolean) {
			if (fade)
				this.tl().fadeIn(200);
			else
				super.show();
		}
		/**
		 * テキストの表示を開始する
		 */
		showText() {
			this.textArea.startAnimation();
		}
		/**
		 * テキストの表示速度を高速にする
		 */
		fastMode() {
			this.textArea.animeSpeed = this.fastSpeed;
		}
		/**
		 * テキストの表示速度を通常速にする
		 */
		normalMode() {
			this.textArea.animeSpeed = this.normalSpeed;
		}
		/**
		 * テキストをすべて表示する
		 */
		showAll() {
			this.textArea.showAll();
		}
		/**
		 * 次のテキストを表示する
		 */
		next() {
			if (this.scriptOffset < 0)
				return false;
			this.oldWipeOut();
			this.setScript(this.script, this.scriptOffset);
			this.textArea.startAnimation();
		}

		/**
		 * 古いテキストをワイプアニメーションで除外する
		 */
		oldWipeOut(time?:number) {
			if (time === undefined)
				time = 800;
			var textArea = this.textArea;
			var old = textArea.createSprite();
			old.moveTo(textArea.x, textArea.y);
			this.append(old);
			var lastLine = textArea.lines[textArea.lines.length - 1];
			var movePoint = lastLine.offsetY + lastLine.height;
			textArea.moveTo(textArea.x, textArea.y + movePoint);
			old.tl().moveBy(0, -textArea.height, time).removeFromScene();
			textArea.tl().moveBy(0, -movePoint, (movePoint / textArea.height) * time);
		}
		/**
		 * 古いテキストをフェードアウトアニメーションで除外する
		 */
		oldFadeOut(time?:number) {
			if (time === undefined)
				time = 500;
			var textArea = this.textArea;
			var old = textArea.createSprite();
			old.moveTo(textArea.x, textArea.y);
			this.append(old);
			old.tl().fadeOut(time).removeFromScene();
		}

		/**
		 * テキスト表示完了時のイベントハンドラ
		 */
		onAnimated() {
			var hasNext = this.scriptOffset >= 0;
			if (hasNext)
				this.showNextCursor();

			this.isReaded = true;
			this.readed.fire(hasNext);
		}
	}
}