///<reference path="all.ts"/>
module jg {
	/**
	 * 文字を表示するクラス
	 */
	export class Label extends E {
		/** 表示する文字列。変更する場合はこのフィールドを直接編集するのではなく、setTextを呼ぶべき */
		text: string;
		/** 最大幅。変更する場合はこのフィールドを直接編集するのではなく、setMaxWidthを呼ぶべき */
		maxWidth: number;
		/** 同期するオブジェクト */
		syncObj: any;
		/** 同期するプロパティ */
		syncProp: string;
		/** 同期時にMath.roundをかけるかどうか */
		syncRound: boolean;

		/**
		 * コンストラクタ
		 * @param text 表示文字列
		 * @param fontSize 文字の大きさ
		 * @param fontColor 文字色
		 * @param baseLine ベースライン
		 */
		constructor(text?:string, fontSize?:number, fontColor?:string, baseline?:string) {
			super();
			this.x = 0;
			this.y = 0;
			if (text) {
				this.setText(text);
			} else {
				this.setText("");
				this.width = 0;
				this.height = 0;
			}
			this.setTextBaseline(baseline ? baseline : "top");
			this.setFontSize(fontSize ? fontSize : 14);
			this.setColor(fontColor ? fontColor : "black");
		}

		/**
		 * 最大幅を変更する。描画される文字列がこの幅を上回る場合、自動的に縮小される
		 * @param maxWidth 最大幅
		 */
		setMaxWidth(maxWidth:number) {
			this.maxWidth = maxWidth;
			this.updateSize();
		}

		/**
		 * 内部サイズを更新する
		 */
		updateSize() {
			var canvas = window.createCanvas(10, 10);
			var ctx = canvas.getContext("2d");
			ctx.font = this.getFont();
			//ctx.textAlign = this.getTextAlign();
			var metrix:TextMetrics = ctx.measureText(this.text);
			this.width = metrix.width;
			this.height = this.getFontSize();
		}

		/**
		 * 文字に影をつける
		 * @param color カラーの色。省略時は黒
		 */
		addShadow(color?:string) {
			this.setDrawOption("shadowBlur", 2);
			this.setDrawOption("shadowColor", color ? color : "black");
		}

		/**
		 * 文字の影を削除する
		 */
		removeShadow() {
			this.removeDrawOption("shadowBlur");
			this.removeDrawOption("shadowColor");
		}

		/**
		 * 表示する文字列を変更する
		 * @param text 変更後の文字列
		 */
		setText(text:string) {
			this.text = text;
			this.updateSize();
			this.updated();
		}

		/**
		 * 文字描画に利用するフォントを変更する。
		 * 指定できる値はCSS Font形式で、かつline-height指定を除いた値。line-heightについては常にnormalに固定される。
		 * @param fontString フォントを現す文字列
		 */
		setFont(fontString:string) {
			this.setDrawOption("font", fontString);
			this.updateSize();
		}

		/**
		 * 現在の文字描画に利用するフォントを取得する
		 */
		getFont():string {
			return this.getDrawOption("font");
		}

		/**
		 * フォントサイズを指定する。
		 * 現在のバージョンではフォントにboldやitalicが指定されているとバグるので注意
		 * @param size 設定するフォントサイズ。単位は常にピクセル
		 */
		setFontSize(size:number) {
			var font = this.getFont();
			var firstPos = font.indexOf(" ");
			this.setFont(size+"px "+font.substr(firstPos+1));
		}

		/**
		 * フォントサイズを取得する。単位は常にピクセル
		 * 現在のバージョンではフォントにboldやitalicが指定されているとバグるので注意
		 */
		getFontSize():number {
			var font = this.getFont();
			var firstPos = font.indexOf(" ");
			try {
				return parseInt(font.substr(0, firstPos-2));
			} catch(ex) {
			}
			return this.height;
		}

		//start, end, left, right, center
		/**
		 * 文字列の寄せ方を、start, end, left, right, centerいずれかの文字列で指定する
		 * @param align 文字列の寄せ方
		 */
		setTextAlign(align:string) {
			this.setDrawOption("textAlign", align);
		}

		/**
		 * 現在の文字列の寄せ方を取得する
		 */
		getTextAlign():string {
			return this.getDrawOption("textAlign");
		}

		/**
		 * 文字列の基準線をtop, hanging, middle, alphabetic, ideographic, bottomのいずれかの文字列で指定する
		 * @param baseline 文字列の基準線
		 */
		setTextBaseline(baseline:string) {
			this.setDrawOption("textBaseline", baseline);
		}

		/**
		 * 現在の文字列の基準線を取得する
		 */
		getTextBaseline():string {
			return this.getDrawOption("textBaseline");
		}

		/**
		 * 文字色を設定する
		 * @param color 設定する文字色。CSSカラーで指定
		 */
		setColor(color:string) {
			this.setDrawOption("fillStyle", color);
		}

		/**
		 * 現在の文字色を取得する
		 */
		getColor():string {
			return this.getDrawOption("fillStyle");
		}

		/**
		 * 表示文字列を特定オブジェクトの状態に同期させる。
		 * sprite.xに同期させる場合は次のようにする。
		 * label.synchronize(sprite, "x", true);
		 * @param obj 同期させるオブジェクト
		 * @param prop 同期させるオブジェクトのプロパティ
		 * @param round 同期時にMath.roundをかけるかどうか。省略時はかけない
		 */
		synchronize(obj:any, prop:string, round?:boolean) {
			this.syncObj = obj;
			this.syncProp = prop;
			this.syncRound = round;
		}

		/**
		 * 描画
		 * @param context 対象の描画コンテキスト
		 */
		draw(context:CanvasRenderingContext2D) {
			if (this.syncObj) {
				var val;
				if (typeof this.syncObj[this.syncProp] == "function")
					val = this.syncObj[this.syncProp](this);
				else
					val = this.syncObj[this.syncProp];

				this.text = this.syncRound ? Math.round(val) : val;
			}
			if (this.maxWidth) {
				context.fillText(
					this.text,
					0,
					0,
					this.maxWidth
				);
			} else {
				context.fillText(
					this.text,
					0,
					0
				);
			}
		}
	}
}