/*
 * @(#)ZResource.java
 *
 * Copyright 2000 by Intelligent Technology Inc. All rights reserved.
 */
package jp.co.iti.fagot.util;

import java.awt.Color;
import java.awt.Window;
import java.awt.Dimension;
import java.awt.Point;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;

import java.net.URL;

import java.util.Vector;
import java.util.Enumeration;
import java.util.ResourceBundle;
import java.util.Properties;
import java.util.Locale;
import java.util.MissingResourceException;

import jp.co.iti.fagot.util.ZGraphicUtil;
/**
 * ZResourceクラスはリソースを管理するためのクラスです。<br>
 * <code>ResourceBundle</code>を保持するクラスで、exceptionしないように
 * カプセル化しています。
 *
 * このクラスで読み込むリソースを優先順位の高い順に記述します。
 * <ul>
 * <li>ユーザディレクトリに存在する動的なユーザ設定プロパティファイル
 * <li>メインアプリケーションのパッケージ名で指定された、codebaseに存在
 * するデフォルトのリソースファイル。
 * </ul>
 *
 * @author  福島康治
 * @version 1.01 2000/12/01
 */
public class ZResource {
	/**
	 * コンストラクタ
	 * @param appClass メインプログラム
	 */
	public ZResource(Class appClass) {
	this( appClass, null );
	}

	/**
	 * コンストラクタ
	 * @param appClass メインプログラム
	 */
	public ZResource(Class appClass, Locale locale) {
	// appクラス保存
	mAppClass  = appClass;

	// ResourceBundleの取得
	String szTmp = "";
	String szAppClass = mAppClass.getName();
	String szStr[] = ZString.tokenize(szAppClass,"." );
	for ( int nIndex = 0 ; nIndex < szStr.length-1 ; nIndex ++ ) {
		szTmp += szStr[nIndex] + "." ;
	}
	String szRes = szTmp + "resources." + szStr[szStr.length-1] ;

	// デフォルト
	try {
//		ZDebug.trace();
		mRes = ResourceBundle.getBundle(szRes);
	} catch (MissingResourceException mre) {
		ZDebug.err(szRes + ".properties not found:"+mre.toString());
		mRes = null;
	}

	// 優先言語用リソースバンドルの取得
	try {
//		ZDebug.trace();
		mPriRes = ResourceBundle.getBundle(szRes,Locale.getDefault());
	} catch (MissingResourceException mre) {
		ZDebug.err(szRes + ".properties not found:"+mre.toString());
		mPriRes = null;
	}

	// プロパティのロード
	mProp = new Properties();
	loadProperty(getPropertyFile());

	mResource = this;
	
	}

	/**
	 * コンストラクタ
	 * @param prop プロパティ
	 */
	public ZResource(Properties prop) {
	// プロパティのロード
	mProp = prop;
	}

	/**
	 * ユーザ定義リソースをロードします。
	 */
	public void loadProperty(String szUsrProps) {
//	ZDebug.trace("load:"+szUsrProps);
	try {
		FileInputStream inStream = new FileInputStream(szUsrProps);
		mProp.load(inStream);
		inStream.close();
    } catch (IOException io) {
		System.out.println("User Properties load failed: " + io);
    }
	}

	/**
	 * ユーザ定義リソースをセーブします。
	 */
	public void saveProperty() {
	String szUsrProps = getPropertyFile();
	try	{
		OutputStream outStream = new FileOutputStream(szUsrProps);
		mProp.store(outStream,mAppClass.getName() + " Properties.");
		outStream.close();
	}
	catch(IOException io)
	{
		ZDebug.err("User Properties save failed: " + io);
	}
	}

	//## static:リソースの取得 ########################################
	/**
	 * プロパティ
	 */
	static public ZResource res() {
	return mResource;
	}

	//## プロパティの取得 #############################################
	/**
	 * ウィンドウ位置を取得します。
	 * @param win ウィンドウ
	 * @param szName ウィンドウ名
	 */
	public void loadGeometry(Window win, String szName ) {
	int x, y, width, height;
	try
	{
		width  = Integer.parseInt(getString("win." + szName + ".width"));
		height = Integer.parseInt(getString("win." + szName + ".height"));
	}
	catch(NumberFormatException nf)
	{  // 初期表示サイズが0x0になるのを防止する
		width  = 400;
		height = 300;
	}
	try
	{
		x = Integer.parseInt(getString("win." + szName + ".x"));
		y = Integer.parseInt(getString("win." + szName + ".y"));
	}
	catch(NumberFormatException nf)
	{	// 取れないときは、画面中央から
		Dimension screen = win.getToolkit().getScreenSize();
		x = (screen.width - width) / 2;
		y = (screen.height - height) / 2;
	}
	win.setLocation(x,y);
	win.setSize(width,height);
	}

	/**
	 * ウィンドウ位置を保存します。
	 * @param win ウィンドウ
	 * @param szName ウィンドウ名
	 */
	public void saveGeometry(Window win, String szName ) {
	Point location = win.getLocation();
	Dimension size = win.getSize();
	mProp.put("win." + szName + ".x",String.valueOf(location.x));
	mProp.put("win." + szName + ".y",String.valueOf(location.y));
	mProp.put("win." + szName + ".width",String.valueOf(size.width));
	mProp.put("win." + szName + ".height",String.valueOf(size.height));
	}

	/**
	 * キーに対応するリソース文字列を取得します。
	 * @param szKey リソースキーワード
	 */
	public String getString(String szKey) {
	String szStr = mProp.getProperty(szKey);
//	ZDebug.trace("getString:"+szKey+"="+szStr);
	if ( szStr == null && mPriRes != null ) {
		try {
		    szStr = mPriRes.getString(szKey);
//		    ZDebug.trace("getString:"+szKey+"="+szStr);
		} catch (MissingResourceException mre) {
		    szStr = null;
//		    ZDebug.trace("Missing:"+szKey);
		}
	}

	if ( szStr == null && mRes != null ) {
		try {
		    szStr = mRes.getString(szKey);
//		    ZDebug.trace("getString:"+szKey+"="+szStr);
		} catch (MissingResourceException mre) {
		    szStr = null;
//		    ZDebug.trace("Missing:"+szKey);
		}
	}

	// RID3 Mac用特殊処理
	if ( szStr != null && szKey.startsWith("rid.") && szKey.endsWith(".dir") ) {
		szStr = ZString.replace(szStr,"/",File.separator);
	}

	return( szStr );
	}

	/**
	 * キーに対応するリソース文字列群を取得します。
	 * リソース文字列群は、キーに続いてシーケンシャルな数値を持ちます
	 * @param szKey リソースキーワード
	 */
	public Vector getStrings(String szKey) {
	Vector vec = new Vector();
	for( int nIndex=1 ; nIndex<100 ; nIndex++ ) {
		String szChildKey = szKey + nIndex ;
		String szValue = getString( szChildKey );
		if ( szValue != null ) {
			vec.add( szValue );
		} else {
			break;
		}
	}
	return vec;
	}

	/**
	 * キーに対応するリソース数値を取得します。
	 * @param szKey リソースキーワード
	 * @param nDefault 未設定の場合のデフォルト値
	 */
	public int getInt(String szKey,int nDefault) {
	String szStr;
	int    nValue;
	szStr = getString(szKey);
	if ( szStr != null ) {
		try {
			nValue = Integer.parseInt(szStr);
		}
		catch(NumberFormatException nf)
		{
			nValue = nDefault ;
		}
	} else {
		nValue = nDefault ;
	}
	return nValue;
	}

	/**
	 * キーに対応する色を取得します。
	 * @param szKey リソースキーワード
	 */
	public Color getColor(String szKey) {
	String szStr = getString(szKey);
	return ZGraphicUtil.stringToColor(szStr);
	}

	/**
	 * キーに対応する色を取得します。
	 *
	 * Color.decode(),Color.getColor()はあてにならないので修正
	 *
	 * @param szStr 色指定文字列
	 */
/*
	static public Color getAwtColor(String szStr) {
	Color  cCol  = null;
	if ( szStr != null && szStr.startsWith("#") ) {
		int nRed   = 0;
		int nGreen = 0;
		int nBlue  = 0;
		try {
			szStr = szStr.substring(1);
			int nSize = szStr.length() / 3;
			nRed  = Integer.parseInt(szStr.substring(0,nSize),16);
			szStr = szStr.substring(nSize);
			nGreen= Integer.parseInt(szStr.substring(0,nSize),16);
			szStr = szStr.substring(nSize);
			nBlue = Integer.parseInt(szStr.substring(0,nSize),16);
		} catch ( NumberFormatException nf ) {
			System.out.println("getAwtColor:parse error");
		}
//		System.out.println("getAwtColor:szStr="+szStr+" R="+nRed+" G="+nGreen+" B="+nBlue);
		cCol = new Color(nRed,nGreen,nBlue);
	}
	if ( cCol == null ) {
//		System.out.println("Color=null" );
		cCol = Color.white;
	}
	return cCol;
	}
*/
	/**
	 * キーに対応するURLを取得します。
	 * @param szKey リソースキーワード
	 */
	public URL getURL(String szKey) {
	String szName = getString(szKey);
	if (szName != null) {
	    URL url = mAppClass.getResource(szName);
	    return url;
	}
	return null;
	}

	/**
	 * キーに対応する真理値を取得します。
	 * 設定されていない場合はfalseを返します
	 * @param szKey リソースキーワード
	 * @param bDefault デフォルト値
	 */
	public boolean getBoolean(String szKey,boolean bDefault) {
	boolean bRet = bDefault;
	String szStr = getString(szKey);
	if ( szStr != null ) {
		if ( szStr.toLowerCase().equals("true") ) {
			bRet = true;
		} else if ( szStr.toLowerCase().equals("false") ) {
			bRet = false;
		}
	}
	return bRet;
	}

	/**
	 * キーに対応する真理値を取得します。
	 * 設定されていない場合はfalseを返します
	 * @param szKey リソースキーワード
	 */
	public boolean getBoolean(String szKey) {
	return getBoolean(szKey,false);
	}


	//## プロパティの設定 #############################################
	/**
	 * キーに対応するリソース文字列を設定します。
	 * @param szKey リソースキーワード
	 * @param szValue 設定値
	 */
	public void putString(String szKey,String szValue) {
	if ( szValue == null ) {
		mProp.remove(szKey);
	} else {
		mProp.put(szKey,szValue);
	}
	}

	/**
	 * キーに対応するリソース文字列群を取得します。
	 * リソース文字列群は、キーに続いてシーケンシャルな数値を持ちます
	 * @param szKey リソースキーワード
	 * @param vec 設定する文字列群
	 */
	public void putStrings(String szKey,Vector vec) {
	Enumeration elm = vec.elements();
	int nIndex = 1;
	while ( elm.hasMoreElements() ) {
		String szChildKey = szKey + nIndex ;
		String szValue = (String)elm.nextElement();
		putString( szChildKey, szValue );
		nIndex++;
	}
	String szEndKey = szKey + nIndex ;
	putString( szEndKey, null );
	}

	/**
	 * キーに対応するリソース文字列を設定します。
	 * @param szKey リソースキーワード
	 * @param nValue 設定値
	 */
	public void putInt(String szKey,int nValue) {
	mProp.put(szKey,String.valueOf(nValue));
	}

	/**
	 * ユーザ定義リソースファイル名を取得します。
	 */
	private String getPropertyFile() {
	String szUsrHome = System.getProperty("user.home");
	String[] szClass = ZString.tokenize(mAppClass.getName(),".");
	String szUsrProps = szUsrHome + File.separator + szClass[szClass.length-1] + ".properties";
	return (szUsrProps);
	}

	/**
	 * カラーを文字列に変換します
	 *
	 * Color.decode(),Color.getColor()はあてにならないので修正
	 *
	 * @param szStr 色指定文字列
	 */
/*
	static public String getAwtColorString(Color c) {
	String szColor = null;
	if ( c != null ) {
		szColor = "#";

		String szRed   = Integer.toHexString(c.getRed());
		if ( szRed.length() == 1 ) {
			szColor += "0" + szRed.toUpperCase();
		} else {
			szColor += szRed.toUpperCase();
		}

		String szGreen = Integer.toHexString(c.getGreen());
		if ( szGreen.length() == 1 ) {
			szColor += "0" + szGreen.toUpperCase();
		} else {
			szColor += szGreen.toUpperCase();
		}

		String szBlue = Integer.toHexString(c.getBlue());
		if ( szBlue.length() == 1 ) {
			szColor += "0" + szBlue.toUpperCase();
		} else {
			szColor += szBlue.toUpperCase();
		}
	}
	return szColor;
	}
*/
	/**
	 * キーに対応する真理値を設定します。
	 * 設定されていない場合はfalseを返します
	 * @param szKey リソースキーワード
	 * @param bValue 設定値
	 */
	public void putBoolean(String szKey,boolean bValue) {
	mProp.put(szKey,(bValue?"True":"False"));
	}

	//## アトリビュート ###############################################
	/**
	 * リソース基準クラス
	 */
	private Class			mAppClass;

    /**
	 * システムリソース
	 */
	private ResourceBundle	mRes;

    /**
	 * システムリソース
	 */
	private ResourceBundle	mPriRes;

    /**
	 * ユーザリソース
	 */
	private Properties		mProp;

	/**
	 * アプリケーションリソース
	 */
	static protected ZResource	mResource = null;
}
