/*
 * @(#)RidGobAction.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : rid gob action
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/05/08
 */
package jp.co.nri.rid.action;

import java.awt.event.ActionEvent;

import java.io.File;
import	java.io.InputStream;
import	java.io.*;

import java.util.Enumeration;
import java.util.Vector;

import javax.swing.JComponent;
import javax.swing.JFileChooser;

import org.w3c.dom.Node;

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

import jp.co.iti.fagot.fob.xml.XElementNS;

import jp.co.iti.fagot.gob.GElement;
import jp.co.iti.fagot.gob.GobManager;

import jp.co.iti.fagot.xml.GRootSVG;

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

import jp.co.iti.fagot.util.ZFileFilter;
import jp.co.iti.fagot.util.ZInstance;
import jp.co.iti.fagot.util.ZResource;
import jp.co.iti.fagot.util.ZReverseEnumeration;
import jp.co.iti.fagot.util.ZDebug;

import jp.co.nri.Rid;

import jp.co.nri.rid.doc.RidElement;
import jp.co.nri.rid.doc.RidElementZone;
import jp.co.nri.rid.doc.RidElementPage;

import jp.co.nri.rid.export.ExportSvgDialog;

import jp.co.nri.rid.generator.GenerateCSV;

import jp.co.nri.rid.xml.*;
import jp.co.nri.rid.RidMIT;


/**
 * Rid Gob系アクションを定義する
 */
public class RidGobAction extends ZAction {
	/**
	 * 唯一のコンストラクタです。
	 * @param app アプリケーション
	 * @param szAction アクション名
	 */
	public RidGobAction(IZApp app,String szAction) {
    super(app,szAction);
	}

	/**
	 * アクション実行
	 */
	public void doAction(ActionEvent e) {
	ZResource res = getApp().getResource();

	// Gridは、どのパネルでも動作可能
	if ( getActionName().equals( GRID ) ) {
		boolean isGrid = res.getBoolean( "edit.grid", true );
		res.putBoolean("edit.grid",!isGrid);
	}

	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	JComponent active = (JComponent)ZInstance.map().get(szTitle);
	if ( !(active instanceof DocPane) ) {
		// アクティブパネルが描画パネルでない場合はとりあえず動作しない
		return;
	}
	DocPane editor = (DocPane)active;
	editor.getDocument().beginTransaction();

	// 上へ
	if ( getActionName().equals( UP ) ) {
		Vector gobs = GobManager.getSelectedElement(szTitle);
		Enumeration elm = new ZReverseEnumeration(gobs);
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			Node parent  = dob.getParentNode();
			Node ref     = dob.getNextSibling();
			// 弟エレメントがあるか？
			while ( ref != null && !(ref instanceof RidElement) ) {
				ref = ref.getNextSibling();
			}
			// 弟エレメントがあれば、弟の後ろに追加
			if ( ref != null ) {
				ref = ref.getNextSibling();
				// 一旦親から削除
				parent.removeChild(dob);
				parent.insertBefore(dob,ref);
			}
		}

		editor.updateGobs();
		editor.repaint();

	// 下へ
	} else if ( getActionName().equals( DOWN ) ) {
		Vector gobs = GobManager.getSelectedElement(szTitle);
		Enumeration elm = gobs.elements();
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			Node parent  = dob.getParentNode();
			Node ref     = dob.getPreviousSibling();
			// 兄エレメントがあるか？
			while ( ref != null && !(ref instanceof RidElement) ) {
				ref = ref.getPreviousSibling();
			}
			// 兄エレメントがあれば、兄の前に追加
			if ( ref != null ) {
				// 一旦親から削除
				parent.removeChild(dob);
				parent.insertBefore(dob,ref);
			}
		}

		editor.updateGobs();
		editor.repaint();

	// ZoneパネルにおけるZoneUnitのシュリンク
	} else if ( getActionName().equals( OMISSION_ZONE_ZONE ) ) {
		Vector gobs = GobManager.getSelectedElement(editor.getPanelId());
		Enumeration elm = gobs.elements();
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			if ( dob instanceof RidElementZone ) {
				XElementNS vwi = dob.getChildElement(".ViewInfo."+editor.getPanelId(),null);
				boolean bOmission = vwi.getBooleanAttr("Omission",false);
				vwi.setBooleanAttr("Omission",!bOmission);
			}
		}
		editor.updateGobs();
		editor.repaint();

	// MapパネルにおけるPageUnitのシュリンク
	} else if ( getActionName().equals( OMISSION_MAP_PAGE ) ) {
		Vector gobs = GobManager.getSelectedElement(editor.getPanelId());
		Enumeration elm = gobs.elements();
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			if ( dob instanceof RidElementPage ) {
				XElementNS vwi = dob.getChildElement(".ViewInfo."+editor.getPanelId(),null);
				boolean bOmission = vwi.getBooleanAttr("Omission",false);
				vwi.setBooleanAttr("Omission",!bOmission);
			}
		}
		editor.updateGobs();
		editor.repaint();

	// SVG出力
	} else if ( getActionName().equals( SVG ) ) {

		String szFile = openFileDialog("svg","SVG File","rid.svg.dir");
		if ( szFile != null ) {
			// ヘッダ
			elementBooster header = null;
			switch(RidMIT.checkMIT()){
			case -3:	// 起動前	ありえないが一応
			case -1:	// ライセンス異常
			case -2:	// trial
				try{
					InputStream in = getClass().getResourceAsStream("/jp/co/nri/resources/header.svg");
					documentBooster doc = new documentBooster(in);
					header = doc.root();
				}catch(Throwable t){}
				
				break;
			case 0:		// 無制限
			default:
				File in = new File(ZInstance.prop().getProperty( Rid.PJ_DIR ) ,getApp().getResource().getString("rid.header.svg"));
				try{
					documentBooster doc = new documentBooster(new FileInputStream(in));
					header = doc.root();
				}catch(Throwable t) {
					ZDebug.err("Parse SVG failed:");
					t.printStackTrace();
				}

			}
			
			// Gobの収集
			Vector gobs = GobManager.list(editor.getPanelId(),GobManager.ALL);
			try {
				GRootSVG svg = new GRootSVG(gobs);
				if(null != header)	svg.setLogo(header.element());
				svg.writeto(szFile ,null);
			} catch ( Exception evt ) {
				ZDebug.err("Write svg failed:");
				evt.printStackTrace();
			}

			// 出力ディレクトリの確認
			String szDocsDir = null;
			String szPjDir = ZInstance.prop().getProperty(Rid.PJ_DIR);
			if ( szPjDir != null ) {
				szDocsDir = szPjDir + File.separator + res.getString("rid.docs.dir");
				String szCompare = szFile.substring(0,Math.min(szFile.length(),szDocsDir.length()));
				if ( szCompare.equalsIgnoreCase(szDocsDir) ) {
                    // コメント入力＆ブラウザ表示有無選択ダイアログ
                    ExportSvgDialog svgd = new ExportSvgDialog();
                    svgd.show(szFile, true);

                } else {
                    ExportSvgDialog svgd = new ExportSvgDialog();
                    svgd.show(szFile, false);
				}
			}

		}
	}
	
	// コミットが抜けていたので追加 20020703
	editor.getDocument().commit();
	}

	/**
	 * UI更新
	 */
	public void update() {
	ZResource res = getApp().getResource();

	boolean bState = false;
	String szTitle = ZInstance.prop().getProperty( Rid.PANEL_ACTIVE );
	JComponent active = (JComponent)ZInstance.map().get(szTitle);
	if ( !(active instanceof DocPane) ) {
		// アクティブパネルが描画パネルでない場合は動作しない
		firePropertyChange(ZAction.ENABLED,null,new Boolean(bState));
		return;
	}
	DocPane editor = (DocPane)active;

	// ゾーンパネルの選択されているGOBを取得
	if ( getActionName().equals( UP ) ) {
		Vector gobs = GobManager.getSelectedElement(szTitle);
		Enumeration elm = new ZReverseEnumeration(gobs);
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			Node parent  = dob.getParentNode();
			Node ref     = dob.getNextSibling();
			// 弟エレメントがあるか？
			while ( ref != null && !(ref instanceof RidElement) ) {
				ref = ref.getNextSibling();
			}
			// 弟エレメントがあれば、弟の後ろに追加
			if ( ref != null ) {
				bState = true;
				break;
			}
		}

	// ゾーンパネルの選択されているGOBを取得
	} else if ( getActionName().equals( DOWN ) ) {
		Vector gobs = GobManager.getSelectedElement(szTitle);
		Enumeration elm = gobs.elements();
		while ( elm.hasMoreElements() ) {
			GElement   gob = (GElement)elm.nextElement();
			DocElement dob = (DocElement)gob.getContainer();
			Node parent  = dob.getParentNode();
			Node ref     = dob.getPreviousSibling();
			// 兄エレメントがあるか？
			while ( ref != null && !(ref instanceof RidElement) ) {
				ref = ref.getPreviousSibling();
			}
			// 兄エレメントがあれば、兄の前に追加
			if ( ref != null ) {
				bState = true;
				break;
			}
		}

	// Grid
	} else if ( getActionName().equals( GRID ) ) {
		boolean isGrid = res.getBoolean( "edit.grid", true );
		firePropertyChange(ZAction.CHECKED,null,new Boolean(isGrid));
		bState = true;

	// ZoneパネルにおけるZoneUnitのシュリンク
	} else if ( getActionName().equals( OMISSION_ZONE_ZONE ) ) {
		Vector gobs = GobManager.getSelectedElement(editor.getPanelId());
		if ( gobs.size() == 1 ) {
			GElement   gob = (GElement)gobs.firstElement();
			DocElement dob = (DocElement)gob.getContainer();
			if ( dob instanceof RidElementZone ) {
				XElementNS vwi = dob.getChildElement(".ViewInfo."+editor.getPanelId(),null);
				boolean bOmission = vwi.getBooleanAttr("Omission",false);
				firePropertyChange(ZAction.CHECKED,null,new Boolean(bOmission));
				bState = true;
			}
		}

	// MapパネルにおけるPageUnitのシュリンク
	} else if ( getActionName().equals( OMISSION_MAP_PAGE ) ) {
		Vector gobs = GobManager.getSelectedElement(editor.getPanelId());
		if ( gobs.size() == 1 ) {
			GElement   gob = (GElement)gobs.firstElement();
			DocElement dob = (DocElement)gob.getContainer();
			if ( dob instanceof RidElementPage ) {
				XElementNS vwi = dob.getChildElement(".ViewInfo."+editor.getPanelId(),null);
				boolean bOmission = vwi.getBooleanAttr("Omission",false);
				firePropertyChange(ZAction.CHECKED,null,new Boolean(bOmission));
				bState = true;
			}
		} else {
			ZDebug.trace("gob:"+gobs.size());
		}

	// SVG出力
	} else if ( getActionName().equals( SVG ) ) {
		// Gobの収集
		Vector gobs = GobManager.list(editor.getPanelId(),GobManager.ALL);
		if ( gobs.size()>0 ) {
			bState = true;
		}
	}

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

	//## ダイアログ ###################################################
	/**
	 * ファイル選択ダイアログ
	 * @param szExt
	 * @param szExtName
	 * @param szOutDir
	 */
	public String openFileDialog(String szExt, String szExtName, String szOutDir) {
	ZResource res = getApp().getResource();
	JFileChooser dlg = new JFileChooser();
	// ファイルフィルタの設定
	dlg.setFileFilter(new ZFileFilter( new String(szExt), szExtName));

	// カレントディレクトリの設定
	String szPjDir = ZInstance.prop().getProperty(Rid.PJ_DIR);
	String szDir = res.getString("app.install.path");
	if ( szPjDir != null ) {
		szDir = szPjDir + File.separator + res.getString(szOutDir);
	}
	dlg.setCurrentDirectory(new File(szDir)) ;

	// ダイアログを開く
	int nRet = dlg.showSaveDialog(getApp().getFrame());
	String szFile = null ;
	if ( nRet == JFileChooser.APPROVE_OPTION) {
		// ファイル名を取得
		File fFile = dlg.getSelectedFile();
		try {
			szFile = fFile.getCanonicalPath();
	    } catch ( java.io.IOException evt) {
			szFile = fFile.getAbsolutePath();
		}

		if( szFile != null ){
			if ( !szFile.endsWith("."+szExt) ) {
				szFile += "."+szExt;
			}
		}
	}

	// ファイル履歴の更新
	// 履歴は更新されないが、dlg.setCurrentDirectoryを行ってディレクトリが
	// 変更になるとメニュー表示でエラーがでるため、ここでファイル履歴を更新する
	getApp().updateRecent( null );

	return szFile;
	}



	//## アトリビュート ###############################################
    /**
     * アクション名(編集)：上へ
     */
	static final public String UP		= "move_up" ;

    /**
     * アクション名(編集)：下へ
     */
	static final public String DOWN		= "move_down" ;

    /**
     * アクション名(編集)：グリッド
     */
	static final public String GRID		= "grid" ;

    /**
     * 表示の調整：ゾーンパネルの省略
     */
	static final public String OMISSION_ZONE_ZONE  = "omission_zone_zone" ;

    /**
     * 表示の調整：マップパネルの省略
     */
	static final public String OMISSION_MAP_PAGE   = "omission_map_page" ;

    /**
     * アクション名(出力)
     */
	static final public String SVG		= "svg" ;
}
