/*
 * The MIT License
 *
 * Copyright 2013 Dra0211.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * 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.
 */
package kinugasa.ui;

import java.io.Serializable;
import kinugasa.contents.resource.Nameable;

/**
 * 入力ウインドウで入力可能な文字のセットと大まかな描画位置を定義するクラスです.
 * <br>
 * 文字セットは一つの文字列を1文字ずつ分解することで選択可能な文字のセットを定義するクラスです。<br>
 * ただし、1つの文字セットに含まれる文字は重複が許容されます。<br>
 * 文字セットに使用する文字列はその描画位置を指定するために改行"\n"およびスペース" "を使用できます。<br>
 * 改行は
 * <br>
 *
 * @version 1.0.0 - 2012/11/24_17:23:37.<br>
 * @author Dra0211<br>
 * <br>
 */
public final class CharSet implements Nameable, Serializable {

	private static final long serialVersionUID = -6702495690225290022L;
	/** この文字セットの名前です. */
	private String name;
	/** この文字セットが使用するすべての文字です. */
	private String values;
	/** 文字セットの描画サイズのフォントサイズに対する係数です. */
	private float drawSizeMag;

	/**
	 * 新しい文字セットを定義します.
	 * 文字セットをグローバルに扱えるようにするには
	 * CharSetHostに追加する必要があります。<br>
	 *
	 * @param name     この文字セットの名前を指定します。<br>
	 * @param charSize 文字の描画サイズを補正する係数です。
	 *                    文字セット中の文字はフォントサイズ*charSizeの幅が「文字の幅」として扱われます。<br>
	 * @param allData  文字データを送信します。スペース" "や改行"\n"を使用できます。<br>
	 *
	 * @throws IllegalArgumentException データ中に全角のアンダースコア"＿"が含まれている場合に投げられます。
	 *                                     "＿"は未入力データを示すために使用されるため、文字セットとしては使用できません。<br>
	 */
	public CharSet(String name, float charSize, String allData) throws IllegalArgumentException {
		if (allData.contains("＿")) {
			throw new IllegalArgumentException("! > CharSet : ctor : cant use \"＿\" : name=["
					+ name + "] bytes=[" + charSize + "] data=[" + allData + "]");
		}
		this.name = name;
		this.drawSizeMag = charSize;
		this.values = allData;
	}

	/**
	 * 文字cがこの文字セットに含まれているか検査します.
	 *
	 * @param c 検査する文字を送信します。<br>
	 *
	 * @return 文字cがこの文字セットに含まれている場合はtrueを返します。<br>
	 */
	public boolean contains(String c) {
		return values.contains(c);
	}

	/**
	 * 文字cがこの文字セットに含まれているか検査します.
	 *
	 * @param c 検査する文字を送信します。<br>
	 *
	 * @return 文字cがこの文字セットに含まれている場合はtrueを返します。<br>
	 */
	public boolean cotnains(char c) {
		return values.contains(Character.toString(c));
	}

	/**
	 * この文字セットのフォントサイズに適用する補正値を取得します.
	 *
	 * @return フォントサイズに適用する補正値を返します。<br>
	 */
	public float getDrawSizeMag() {
		return drawSizeMag;
	}

	/**
	 * フォントサイズを補正し、この文字セットに含まれる文字の等幅の適切なサイズを返します.
	 *
	 * @param fontSize 補正するフォントサイズを送信します。<br>
	 *
	 * @return fontSIze * getDrawSizeMag()を返します。<br>
	 */
	public float convertSize(float fontSize) {
		return fontSize * drawSizeMag;
	}

	/**
	 * この文字セットで使用されるすべての文字が含まれた文字列を返します.
	 *
	 * @return コンストラクタで指定された使用する文字を返します。<br>
	 */
	public String getValues() {
		return values;
	}

	/**
	 * 文字セット内の文字を分解し、1文字ごとにテキストラベルに発行します.
	 *
	 * @param startX     最も左上のラベルを配置するX座標を指定します。<br>
	 * @param startY     最も左上のラベルを配置するY座標を指定します。<br>
	 * @param labelModel 使用するラベルモデルを指定します。クローンされません。<br>
	 *
	 * @return 指定した条件で作成したこの文字セットの表示用ラベルを2次元に配置して返します。<br>
	 */
	public TextLabel[][] parse(float startX, float startY, LabelModel labelModel) {
		TextLabel[][] result = new TextLabel[rowNum()][];
		float charSize = labelModel.getFontSize() + 2;
		String[] lines = values.split("\n");
		for (int yIdx = 0; yIdx < lines.length; yIdx++) {
			char[] lineData = lines[yIdx].toCharArray();
			result[yIdx] = new TextLabel[lineData.length];
			for (int xIdx = 0; xIdx < lineData.length; xIdx++) {
				result[yIdx][xIdx] = new TextLabel(
						startX + xIdx * charSize,
						startY + yIdx * charSize,
						Character.toString(lineData[xIdx]), labelModel);
			}
		}
		return result;
	}

	/**
	 * この文字セットの行数を返します.
	 *
	 * @return この文字セットを構築した際の行数を返します。<br>
	 */
	public int rowNum() {
		return values.split("\n").length;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return "CharSet{" + "name=" + name + ", values=" + values + '}';
	}
}
