package jp.ac.kyutech.mns.ist.sheetmap;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.StringTokenizer;

import jp.ac.kyutech.mns.ist.util.FileReadWriter;

/**
 * 設定項目（プロパティ）オブジェクト．コンストラクタで設定ファイル(*.ssf)を読み込み，自分自身の変数のデフォルト値をリフレクションによって変更する．
 * @author miuramo
 *
 */
public class ATNProperty {
	/**
	 * 生徒パネルの行数（横にいくつ並べるか）
	 */
	public int column = 6;
	/**
	 * 生徒パネルの列数（縦にいくつ並べるか）
	 */
	public int row = 6;

	/**
	 * 生徒パネルの幅ピクセル数
	 */
	public int stsizex = 700;
	/**
	 * 生徒パネルの高さピクセル数
	 */
	public int stsizey = 990;
	/**
	 * Web公開用生徒パネルの幅ピクセル数
	 */
	public int webstsizex = 500;
	/**
	 * Web公開用生徒パネルの高さピクセル数
	 */
	public int webstsizey = 707;
	/**
	 * 並べるときの間隔
	 */
	public int space = 10;
	/**
	 * ATNWindow表示の幅
	 */
	public int viewsizex = 592;
	/**
	 * ATNWindow表示の高さ
	 */
	public int viewsizey = 876;
	/**
	 * ATNWindow表示の位置（x座標）
	 */
	public int viewlocx = 0;
	/**
	 * ATNWindow表示の位置（y座標）
	 */
	public int viewlocy = 0;

	/**
	 * ATNWindow表示のスナッピング設定・位置
	 * (0 なし,  1 = 左上  2=右上  3=左下  4=右下)
	 * (viewlocx, viewlocy を上書きします)
	 */
	public int viewsnapping = 2;
	/**
	 * 生徒ボタンパネルの位置，大きさ
	 */
	public int sbsizex = 600;
	public int sbsizey = 600;
	public int sblocx = 400;
	public int sblocy = 100;

	/**
	 * 生徒ボタンパネルのスナッピング設定・位置
	 * (0 なし,  1 = 左上  2=右上  3=左下  4=右下)
	 * (sblocx, sblocy を上書きします)
	 */
	public int sbsnapping = 7;
	/**
	 * 再描画の間隔
	 */
	public int repaintinterval = 1000;

	/**
	 * 筆記縮小率（超音波ペンのときは，A4の横幅解像度が3300で，stsizex=600だった）
	 */
	public float inkscale = 0.181818f; // 600/3300
	/**
	 * マウス描画の筆記を，DBに保存するときに変換するために使用
	 */
	public float inkscale700 = 0.212121f; // 700/3300

	/**
	 * 筆記の線幅
	 */
	public float inkwidth = 1.0f;

	// public float imagewidth = 600.0f;
	// public float imageoffsetx = 0.0f;
	// public float imageoffsety = 10.0f;
	// for control panel
	/**
	 * コントロールパネルの生徒ボタンの幅
	 */
	public int cpstsizex = 30;
	/**
	 * コントロールパネルの生徒ボタンの高さ
	 */
	public int cpstsizey = 20;
	/**
	 * コントロールパネルの生徒ボタンの配置間隔
	 */
	public int cpspace = 2;
	/**
	 * コントロールパネルの生徒ボタンを配置する左上座標
	 */
	public int cplocx = 0;
	/**
	 * コントロールパネルの生徒ボタンを配置する左上座標
	 */
	public int cplocy = 0;


	public int animsec = 1000;

	/**
	 * アニメーション速度（早）
	 */
	public int animsec_fast = 0;
	/**
	 * アニメーション速度（中）
	 */
	public int animsec_mid = 2000;

	/**
	 * アニメーション速度（遅）
	 */
	public int animsec_slow = 5000;

	public String PNodePropEntityFile = "PNodePropEntity.ser";
	/**
	 * （現在は未使用）いくつ筆記が貯まったら保存するか
	 */
	//	public int maxstorestrokes = 1000000;
	/**
	 * （現在は未使用）PDAからのアクセス用，AirTransNote Serverポート番号
	 */
	//	public int snail_port = 10007;
	/**
	 * デバッグ用のログを吐き出すかどうか
	 * （現在は，筆記の圧力を標準出力に表示する=true）
	 */
	public boolean printsendlog = false;
	/**
	 * （現在は未使用）生徒の席順配置
	 */
	//	public String seatlayout = "";
	/**
	 * 起動時に読み込むPage定義ファイル(*.ser)
	 * : （コロン）でくぎって１〜４ページまで設定できる
	 * 例：math27-1.ser:math27-2.ser:math27-3.ser:pat2.ser
	 */
	public String book_file = "";

	/**
	 * 起動時に，読み込む画像ファイル
	 */
	public String image_file = "sheet1.png:sheet2.png:sheet3.png:sheet4.png:sheet5.png:sheet6.png";

	/**
	 * mysql接続ユーザ名
	 */
	public String mysql_user = "atnuser";
	/**
	 * mysql接続パスワード
	 */
	public String mysql_pass = "atnuser";
	/**
	 * mysql接続ホスト
	 */
	public String mysql_host = "localhost";
	/**
	 * mysql接続DB名
	 */
	public String mysql_db = "atnrepos";

	/**
	 * リモート操作(クライアントの場合，サーバのIPアドレスを設定)
	 */
	public String server = "";

	/**
	 * 教師画面モード
	 */
	public boolean teachermode = false;

	/**
	 * キャッシュを使う方針(always, ask, neverから選択)
	 */
	public String useCache = "ask";

	/**
	 * 講義を開始（DB読み込みを開始）する方針(always, ask, neverから選択)
	 */
	public String startLecture = "ask";

	/**
	 * 起動時に開く講義の番号（1以上が有効）
	 */
	public int openLecture = 0;

	/**
	 * 文字認識辞書
	 */
	public String recogdicfile = "numeric3.dic";

	public String dictdata = "";

	//	public boolean enquete_mode = false;

	/**
	 * 座席設定ファイル
	 */
	public String seatmap_file = "";

	/**
	 * ホイール回転ズーム方向の設定(-1 または 1)
	 */
	public int wheelrotationdirection = -1;

	/**
	 * 座席ボタンのデフォルトの回転方向=180度
	 */
	public int seatButtonRotation = 2;
	public int seatButtonRotation_waitmsec = 10000; //10秒

	/**
	 * 印刷余白
	 */
	public double printmargin_top = 6;
	public double printmargin_left = 5;
	public double printmargin_right = 5;
	public double printmargin_bottom = 10;

	/**
	 * カーソルオーバーでアクティブ
	 */
	public boolean winactivatewhencursorenter = true;

	protected String helpurl = "http://css.jaist.ac.jp/~miuramo/cgi-bin/fswiki/wiki.cgi/atn";

	public boolean showTooltip = false; //ツールチップ表示する？",
	public boolean showSPCoverCB = false; //生徒パネルに生徒名前/ペン番号を表示する？",
	public boolean showStuNameOnSPCover = false;// 生徒パネルに生徒の名前を表示するならtrue，ペン番号ならfalse",
	public boolean showRegionCB = true  ;// 領域を表示する？",
	public boolean showColorRegionCB = true;// 領域の枠線の色を表示する？",
	public boolean showResultCB = true     ;// 領域の認識結果を表示する？",
	public boolean showInkCB = true        ;// 生徒のペンを表示する？",
	public boolean showMaskCB = true       ;// 秘匿マスクを表示する？",
	public boolean showRedInkCB = true     ;// 教師の赤ペンを表示する？",
	public boolean showImgCB = true        ;// 紙の印刷イメージを表示する？",
	public boolean showNoLoginPanelCB = true;// 未ログインのパネルを表示する？",
	
	
	/**
	 * 設定ファイルを読み込んだ，プロパティオブジェクトを返します
	 * @param fname 設定ファイル
	 */
	public ATNProperty(String fname) {
		String[] lines = FileReadWriter.getLines(fname);
		String line;
		StringTokenizer st2;
		for (int i = 0; i < lines.length; i++) {
			// System.out.println(lines[i]);
			int index = lines[i].indexOf(";");
			if (index > -1) {
				line = lines[i].substring(0, index);
			} else {
				line = lines[i];
			}
			System.out.println(line);
			st2 = new StringTokenizer(line, "=");
			if (st2.countTokens() == 2) {
				String finame = st2.nextToken().trim();
				String val = st2.nextToken().trim();
				Object o = gen_primitive(this, finame, val);
				setter(this, finame, o);
			}
		}
	}
	public ATNProperty(){
//		int res = JOptionPane.showConfirmDialog(null, "設定ファイル (ssf.txt) が見つかりません．\n\n雛形を新規作成しますか？\n\n" +
//				"「はい」を押すと，config.ssf.txt, config2.ssf.txt, seat.map.txt\n" +
//		"の３つのファイルを上書き出力します．\n" +
//		"「いいえ」を押すと，設定ファイルを作成せずにデフォルト設定での起動を試みます．\n"+
//		"「取消し」を押すと，プログラムを終了します．");
//		if (res == JOptionPane.YES_OPTION){
//			String[] content = {
//					"; ATN設定ファイル",
//					"; （セミコロン以降は無視されます）",
//					"; ATN設定ファイルのファイル名は，.ssf.txt で終わっている必要があります．",
//					"",
//					"column = 6   ; 横に並んだ列の数",
//					"row = 6      ; 縦に並んだ行の数",
//					"seatmap_file = seat.map.txt  ; 座席設定ファイルを指定（座席と名前，ペン番号の対応表）",
//					"",
//					"teachermode = false ; 教師画面モードで起動するか？ true,falseから選択",
//					"useCache = always  ; キャッシュ利用するか？        always,ask,neverから選択",
//					"startLecture = ask ; DBからの読み込み開始するか？  always,ask,neverから選択",
//					"openLecture = 0    ; 起動時に自動的に開く講義番号．1以上であれば有効になる．",
//					"",
//					";server = 192.168.0.1 ; リモート操作(クライアントの場合，サーバのIPアドレスを設定)",
//					"mysql_user = atnuser   ; mysql接続ユーザ名",
//					"mysql_pass = atnuser   ; mysql接続パスワード",
//					"mysql_host = localhost ; mysql接続ホスト(クライアントの場合はサーバのIPアドレスを設定)",
//					"mysql_db = atnrepos    ; mysql接続DB名",
//					"",
//					"wheelrotationdirection = -1  ; ホイールの回転ズーム方向   -1,1から選択",
//					"",
//					"; 表示レイヤーの初期設定",
//					"showTooltip = false  ; ツールチップ表示する？",
//					"showSPCoverCB = false; 生徒パネルに生徒名前/ペン番号を表示する？",
//					"showStuNameOnSPCover = false; 生徒パネルに生徒の名前を表示するならtrue，ペン番号ならfalse",
//					"showRegionCB = true  ; 領域を表示する？",
//					"showColorRegionCB = true; 領域の枠線の色を表示する？",
//					"showResultCB = true     ; 領域の認識結果を表示する？",
//					"showInkCB = true        ; 生徒のペンを表示する？",
//					"showMaskCB = true       ; 秘匿マスクを表示する？",
//					"showRedInkCB = true     ; 教師の赤ペンを表示する？",
//					"showImgCB = true        ; 紙の印刷イメージを表示する？",
//					"showNoLoginPanelCB = true; 未ログインのパネルを表示する？",
//					"",
//			};
//
//			FileReadWriter.putLines("config.ssf.txt", content);
//			FileReadWriter.putLines("config2.ssf.txt", content);
//
//			String[] content2 = {
//					"# 座席設定ファイル",
//					"# # や ; で開始する行は，無視されます．",
//					"# 座席設定ファイルのファイル名は，.ssf.txt で終わっている必要があります．",
//					"# 座席表（名前）を記述した後，座席割り当て（ペン番号）を記述してください．",
//					"",
//					"# 座席表（名前）",
//					"# 半角数字以外で書くと，名前として順番に割り当てられます．",
//					"# 教師から見て，教室後ろの廊下側から順に，全角スペースで",
//					"# 区切って書いてください．",
//					"# 空席は ＝＝ または ==== または ---- と書いてください．",
//					"",
//					"田中　＝＝　木村　松下　酒井　遠藤　",
//					"篠原　竹内　石坂　小出　坂本　平田",
//					"吉田　中村　尾家　大越　小田部　古川",
//					"安田　木内　小西　藤原　井上　岡崎",
//					"小黒　小林　野田　古賀　廣瀬　宮野",
//					"新見　藤尾　伊藤　安部　徳田　永山",
//					"林　　石原　鈴木　清水　岡本　大内",
//					"",
//					"# 座席の数よりも多い場合は，無視されます．",
//					"山崎　大橋　松山　西野　中川　高木",
//					"大石　吉田　平林",
//					"",
//					"# 座席割り当て（ペン番号）",
//					"## 半角数字で書くと，ペン番号として順番に割り当てられます．",
//					"# 教師から見て，教室後ろの廊下側から順に，半角スペースで",
//					"# 区切って書いてください．空席は == または -- とします．",
//					"01 -- 03 04 05 06",
//					"07 08 09 10 11 12",
//					"13 14 15 16 17 18",
//					"19 20 21 22 23 24",
//					"25 26 27 28 29 30",
//					"31 32 33 34 35 36",
//			""};
//
//			FileReadWriter.putLines("seat.map.txt", content2);
//
//			JOptionPane.showMessageDialog(null, "雛形設定ファイルを書き出しました．\nお手数ですが，雛形設定ファイルを読み込むには，再度ATNを起動してください．\n\n" +
//			"「了解」を押すと，プログラムを終了します．");
//			System.exit(0);
//		} else if (res == JOptionPane.CANCEL_OPTION){
//			System.exit(0);
//		}

	}

	public static final Class<?> getWrapperClass(Class<?> primitiveClass) {
		Class<?> wrapper = null;
		if (primitiveClass == Boolean.TYPE)
			wrapper = java.lang.Boolean.class;
		else if (primitiveClass == Character.TYPE)
			wrapper = java.lang.Character.class;
		else if (primitiveClass == Byte.TYPE)
			wrapper = java.lang.Byte.class;
		else if (primitiveClass == Short.TYPE)
			wrapper = java.lang.Short.class;
		else if (primitiveClass == Integer.TYPE)
			wrapper = java.lang.Integer.class;
		else if (primitiveClass == Long.TYPE)
			wrapper = java.lang.Long.class;
		else if (primitiveClass == Float.TYPE)
			wrapper = java.lang.Float.class;
		else if (primitiveClass == Double.TYPE)
			wrapper = java.lang.Double.class;
		else if (primitiveClass == java.lang.String.class)
			wrapper = java.lang.String.class;
		return wrapper;
	}

	//	public void test() {
	//		try {
	//			// クラスを取得
	//			Class c = Class.forName("jaist.css.atn.ATNProperty");
	//			// アクセス可能なフィールドをリフレクトする
	//			Field[] field = c.getFields();
	//			System.out.println("----- アクセス可能なフィールド -------");
	//			for (int i = 0; i < field.length; i++) {
	//				String fieldname = field[i].toString();
	//				System.out.print(fieldname + " ");
	//				System.out.println(field[i].get(this).toString());
	//			}
	//			System.out.println();
	//		} catch (Exception ex) {
	//			ex.printStackTrace(System.out);
	//		}
	//	}

	public static Object gen_primitive(Object obj, String fieldname,
			String value) {
		try {
			// (1) determine target wrapper class of primitive
			Class cthis = obj.getClass();
			Field f = cthis.getField(fieldname);
			// System.out.println(f.getType().toString());
			Class pclass = getWrapperClass(f.getType());
			// System.out.println(pclass.toString());
			Class[] pconstcarg = new Class[1];
			pconstcarg[0] = Class.forName("java.lang.String");
			Constructor pconst = pclass.getConstructor(pconstcarg);
			Object[] parg = new Object[1];
			parg[0] = value;
			return pconst.newInstance(parg);
		} catch (Exception ex) {
			ex.printStackTrace(System.out);
		}
		return null;
	}

	// obj: 対象オブジェクト，fieldname 対象フィールド, o 変更後の値
	public static void setter(Object obj, String fieldname, Object o) {
		try {
			Class<?> c = obj.getClass();
			Field f = c.getField(fieldname);
			StringBuffer sb = new StringBuffer();
			sb.append("  | " + fieldname + " : ");
			sb.append(f.get(obj).toString() + " -> ");
			f.set(obj, o);
			sb.append(f.get(obj).toString());
			System.out.println(sb.toString());
		} catch (Exception ex) {
			ex.printStackTrace(System.out);
		}
	}
}
