/*
 * @(#)RidExecAction.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : 他アプリ起動系 Action
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/11/07
 */
package jp.co.nri.rid.doc;

import java.awt.event.ActionEvent;

import java.io.File;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

import java.util.Vector;

import jp.co.iti.fagot.ZApp;

import jp.co.iti.fagot.action.ZAction;

import jp.co.iti.fagot.doc.DocElement;

import jp.co.iti.fagot.util.ZInstance;
import jp.co.iti.fagot.util.ZResource;
import jp.co.iti.fagot.util.ZString;
import jp.co.iti.fagot.util.ZDebug;

import jp.co.nri.Rid;
import jp.co.nri.Ridual;

import jp.co.nri.rid.doc.RidElementUrl;

import jp.co.nri.rid.environment.MessageDialog;
import jp.co.nri.rid.error.RidMessage;
/**
 * Rid 他アプリ起動系 Action
 */
public class RidExecAction extends RidAction {
	/**
	 * アクション実行
	 */
	public void doAction(ActionEvent evt) {
	String szAction = getActionName();
	Vector targets  = getTargets();

	String szFil = null;
	String szCmd = null;
	if ( targets.size() == 0 ) {
		ZResource res = ZApp.getTheApp().getResource();
		String szPjDir = ZInstance.prop().getProperty( Rid.PJ_DIR );
		if ( szAction.equals( EXEC_BRWS ) ) {
			szCmd  = res.getString("generate.browser_command");
			szFil = szPjDir+File.separator
					+res.getString("rid.admin.dir")+File.separator
					+"index.html";
//			try{ szFil = new File(szFil).toURL().toExternalForm(); }
//			catch(java.net.MalformedURLException e){ e.printStackTrace(); }
		} else if ( szAction.equals( EXEC_TEXT ) ) {
			RidApplication app = (RidApplication)ZInstance.map().get( Rid.APPLICATION );
			szCmd = res.getString("command.text.editor");;
			szFil = app.getFileName();
		} else if ( szAction.equals( PLAN_HTML ) ) {
			szCmd = res.getString("command.html.editor");;
			szFil = szPjDir+File.separator
					+res.getString("rid.plan.dir")+File.separator
					+"project.html";
		} else if ( szAction.equals( PLAN_TEXT ) ) {
			szCmd = res.getString("command.text.editor");;
			szFil = szPjDir+File.separator
					+res.getString("rid.plan.dir")+File.separator
					+"project.html";
		}
	} else if ( targets.size() == 1 ) {
		String[] szCommand = getCommand((DocElement)targets.firstElement());
		if ( szCommand != null ) {
			szCmd = szCommand[0];
			szFil = szCommand[1];
		}
	}

	if ( szCmd != null ) {
		if ( !exec( szCmd, szFil ) ) {
			RidMessage ridMsg = new RidMessage();
			MessageDialog.showError(ridMsg.Error("E1901",szCmd+" "+szFil));
		}
	}
	}

	/**
	 * UI更新
	 */
	public void update() {
	String szAction = getActionName();
	boolean bState = true;

	// プロジェクトディレクトリの取得
	String szPjDir = ZInstance.prop().getProperty(Rid.PJ_DIR);
	if ( szPjDir == null ) {
		bState = false;
	} else {
		// 選択されているエレメントの数
		int nTargetCnt = getTargetsSize();
		if ( nTargetCnt == 0 ) {
			if ( szAction.equals( EXEC_BRWS ) ||
				 szAction.equals( EXEC_TEXT ) ||
				 szAction.equals( PLAN_HTML ) ||
				 szAction.equals( PLAN_TEXT ) ) {
				bState = true;
			}
		} else if ( nTargetCnt == 1 ) {
			bState = true;
			if ( szAction.equals( EXEC_EXPL ) ||
				 szAction.equals( EXEC_PRDC ) ||
				 szAction.equals( EXEC_PRSN ) ||
				 szAction.equals( EXEC_BRWS ) ||
				 szAction.equals( EXEC_HTML ) ||
				 szAction.equals( EXEC_TEXT ) ) {
				String[] szCmd = getCommand(getTarget());
				if ( szCmd == null ) {
					bState = false;
				}
			}
		} else {	// 複数の場合はdisable
			bState = false;
		}
	}

	firePropertyChange(ZAction.ENABLED,null,new Boolean(bState));
	}

	/**
	 * ターゲットコマンドの取得
	 * @param target 選択されているエレメント
	 * @return コマンド名とファイル名を配列で返す
	 */
	protected String[] getCommand(DocElement target) {
	String szAction = getActionName();
	ZResource res = ZApp.getTheApp().getResource();

	String szFile = target.getAttribute("Key");
	String szPath = ZString.replace(szFile,"/",File.separator);
	String szPj   = ZInstance.prop().getProperty( Rid.PJ_DIR )+File.separator ;
	boolean bExistCheck = true;

	// 取得するコマンド名とファイル名
	String szCmd = null;
	String szTrg = null;

	if (        szAction.equals( EXEC_EXPL ) ) {
//		szTrg = szPj+res.getString("rid.html.dir")+File.separator+szPath;
		szTrg = Ridual.getHtmlDir()+File.separator+szPath;
		szCmd = res.getString("command.explorer");
	} else if ( szAction.equals( EXEC_PRDC ) ) {
		szTrg = szPj+res.getString("rid.team.dir")+File.separator+szPath+"_frame.html";
		szCmd = res.getString("generate.browser_command");
	} else if ( szAction.equals( EXEC_PRSN ) ) {
		szTrg = szPj+res.getString("rid.public.dir")+File.separator+szPath+"_frame.html";
		szCmd = res.getString("generate.browser_command");
	} else if ( szAction.equals( EXEC_BRWS ) ) {
		if ( target instanceof RidElementUrl ) {
			szTrg = szFile;
			bExistCheck = false;
		} else {
//			szTrg = szPj+res.getString("rid.html.dir")+File.separator+szPath;
			szTrg = Ridual.getHtmlDir()+File.separator+szPath;
			szTrg = new File(szTrg).getAbsolutePath();
//			try{ szTrg = new File(szTrg).toURL().toExternalForm(); }
//			catch(java.net.MalformedURLException e){ e.printStackTrace(); }
		}
		szCmd = res.getString("generate.browser_command");

	} else if ( szAction.equals( EXEC_HTML ) ) {
//		szTrg = szPj+res.getString("rid.html.dir")+File.separator+szPath;
		szTrg = Ridual.getHtmlDir()+File.separator+szPath;
		szCmd = res.getString("command.html.editor");
	} else if ( szAction.equals( EXEC_TEXT ) ) {
//		szTrg = szPj+res.getString("rid.html.dir")+File.separator+szPath;
		szTrg = Ridual.getHtmlDir()+File.separator+szPath;
		szCmd = res.getString("command.text.editor");
	}

	// 存在チェック
	if ( bExistCheck ) {
		File fFile = new File( szTrg );
		if ( !fFile.exists() ) {
//			ZDebug.trace("Target not exist:"+szTarget);
			szCmd = null;
		}
	}

	// 存在した場合は、コマンド名＋ターゲットを返す
	String[] szRet = null ;
	if ( szCmd != null ) {
		szRet = new String[2];
		szRet[0] = szCmd;
		szRet[1] = szTrg;
	}
	return szRet;
	}

	/**
	 * コマンドの実行
	 * @param szCmd コマンド名
	 * @param szFil ファイル名
	 */
	static public boolean exec(String szCmd, String szFil) {
	boolean bRet = true;
	try {
		ZDebug.trace("exec:"+szCmd+" "+szFil);

		// 先頭がダブルクォートか？
		boolean bInQuote = false;
		String szFirst = ZString.trimLeft(szCmd);
		if ( szFirst.startsWith("\"") ) {
			bInQuote = true;
		}
		// ダブルクォートで分割されていればそれを取り出す
		Vector cmds = new Vector();
		String[] sz1 = ZString.tokenize( szCmd, "\"" );
		if ( sz1.length == 1 ) {
			String szCommand = szCmd + " " + szFil ;
			Process ap = Runtime.getRuntime().exec(szCommand);
			StderrThread thread = new StderrThread(ap);
		} else {
			// ダブルクォートでくくられている場合は配列型呼び出し
			for ( int nAt=0 ; nAt< sz1.length ; nAt++ ) {
				if ( bInQuote ) {
					// ダブルクォート内はそのまま
					cmds.add( sz1[nAt] );
				} else {
					// ダブルクォート外はスペースで区切る
					String[] sz2 = ZString.tokenize( sz1[nAt] );
					for ( int nAt2=0 ; nAt2<sz2.length ; nAt2++ ) {
						cmds.add( sz2[nAt2] );
					}
				}
				bInQuote = !bInQuote;
			}

			// コマンドの作成
			String[] szCommand = new String[cmds.size()+1];
			int nAt = 0;
			for ( nAt=0 ; nAt<cmds.size() ; nAt++ ) {
				szCommand[nAt] = (String)cmds.elementAt(nAt);
				ZDebug.trace("\t div:"+szCommand[nAt]);
			}
			szCommand[nAt] = szFil;

			Process ap = Runtime.getRuntime().exec(szCommand);
			StderrThread thread = new StderrThread(ap);
		}

	} catch ( Exception e ) {
		ZDebug.err( "Error:"+e );
		bRet = false;
	}
	return bRet;
	}

	//## サブクラス ###################################################
	/**
	 * アプリケーション実行時のエラー取得スレッド
	 */
	static class StderrThread extends Thread {
	StderrThread(Process ap) {
		super("*** Application stderr read thread ***");
		mAp = ap;
		start();
	}
	/**
	 * 実行
	 */
	public void run() {
	try	{
		BufferedReader in = new BufferedReader(
			new InputStreamReader(mAp.getErrorStream()));

		String szLine;
		while((szLine = in.readLine()) != null) {
			ZDebug.trace( "***app***:"+szLine );
		}
		in.close();
	} catch(IOException io) {
			ZDebug.trace( "***app***:IOERR:"+io.getMessage() );
	}
	}
	Process mAp = null;
	}

	//## アトリビュート ###############################################
    /**
     * アプリケーション実行：エクスプローラ
     */
	final static public String EXEC_EXPL	= "exec_expl" ;

    /**
     * アプリケーション実行：製作指示書
     */
	final static public String EXEC_PRDC	= "exec_prdc" ;

    /**
     * アプリケーション実行：紙芝居
     */
	final static public String EXEC_PRSN	= "exec_prsn" ;

    /**
     * アプリケーション実行：HTMLブラウズ
     */
	final static public String EXEC_BRWS	= "exec_brws" ;

    /**
     * アプリケーション実行：HTMLエディタ
     */
	final static public String EXEC_HTML	= "exec_html" ;

    /**
     * アプリケーション実行：Textエディタ
     */
	final static public String EXEC_TEXT	= "exec_text" ;

    /**
     * アプリケーション実行：HTMLエディタ：plan file
     */
	final static public String PLAN_HTML	= "plan_html" ;

    /**
     * アプリケーション実行：Textエディタ：plan file
     */
	final static public String PLAN_TEXT	= "plan_text" ;
}
