/*
 * @(#)RidElementScenarioItem.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : ScenarioItem
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/11/07
 */
package jp.co.nri.rid.doc;

import java.awt.Color;

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

import org.w3c.dom.DOMException;
import org.w3c.dom.Node;

import jp.co.iti.fagot.fob.FColor;

import jp.co.iti.fagot.geom.ZPoint;
import jp.co.iti.fagot.geom.ZPath;
import jp.co.iti.fagot.geom.ZLine;
import jp.co.iti.fagot.geom.ZRectangle;

import jp.co.iti.fagot.gob.GElement;
import jp.co.iti.fagot.gob.GPath;
import jp.co.iti.fagot.gob.GLine;
import jp.co.iti.fagot.gob.GOperation;
import jp.co.iti.fagot.gob.GobManager;

import jp.co.iti.fagot.doc.DocPane;
import jp.co.iti.fagot.doc.DocGridControler;

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

import jp.co.nri.Rid;
/**
 * Rid Element(ScenarioItem用)
 */
public class RidElementScenarioItem extends RidElement {

	/**
	 * デフォルトコンストラクタ
	 */
	public RidElementScenarioItem() throws DOMException {
	}

	//## IGobContainer：移動 ##########################################
	/**
	 * 要素の移動モードはなにか？
	 * @param gob リクエスト元Gob
	 * @param pt   論理座標
	 */
	public byte getPreMoveMode(GElement gob,ZPoint pt) {
	byte mode = super.getPreMoveMode(gob,pt);
	switch ( mode ) {
	  case GOperation.MOVE:		// 移動
		mode = GOperation.NONE;
		break;

	  case GOperation.NEW:		// 新規作成
		// ヒットするエレメントがあれば、オプション（接続予定マーク）を表示
		DocPane panel = (DocPane)ZInstance.map().get( Rid.PANEL_MAP );
		String szPanelId = panel.getPanelId();
		if ( findContainer(szPanelId,pt,null) ) {
			getContainer(1).setHighlight(szPanelId,GOperation.MOVE);
		}
		break;
	  case GOperation.POINT:	// 次のアイテムの移動
		break;
	}
	return mode;
	}

	/**
	 * 移動の開始
	 * @param gob  リクエスト元Gob
	 * @param grid グリッドコントローラ
	 */
	public void moveStart(GElement gob,DocGridControler grid) {
	}

	/**
	 * 移動中Pathの取得
	 * @param gob  リクエスト元Gob
	 * @param grid グリッドコントローラ
	 */
	public ZPath getMovingPath(GElement gob,DocGridControler grid) {
//	ZDebug.trace();
	DocPane editor = grid.getEditor();
	ZPoint ptMove = grid.getMovePoint();
	ZPath path = new ZPath();

	switch ( grid.getMoveMode() ) {
	  case GOperation.NEW:		// 新規作成
	  case GOperation.POINT:	// 点の移動
		// 移動点に接続コンテナがある場合は、接続コンテナから移動点を取得
		if ( findContainer(editor.getPanelId(),ptMove,null) ) {
			RidElementPage page = getContainer(1);
			page.setHighlight(editor.getPanelId(),GOperation.MOVE);
			path = page.getMapScenarioPath(editor.getPanelId());
		}
		break;
	}

	return path;
	}

	/**
	 * 移動の完了
	 * @param gob  リクエスト元Gob
	 * @param grid グリッドコントローラ
	 */
	public void moveEnd(GElement gob,DocGridControler grid) {
	DocPane editor = grid.getEditor();
	ZPoint ptMove = grid.getMovePoint();

	switch ( grid.getMoveMode() ) {
	  case GOperation.NEW:		// 新規作成
		if ( findContainer(editor.getPanelId(),ptMove,null) ) {
			updateContainer(editor.getPanelId());
			setSelect(gob,true);
			RidDocumentSite doc = (RidDocumentSite)editor.getDocument();
			setDocument( doc );
			RidElementScenario scene = doc.getScenario( doc.getScenarioName() );
			if ( scene != null ) {
				scene.appendChild(this);
			}
		}
		break;

	  case GOperation.POINT:	// 点の移動
		break;
	}

	}

	//## 描画 #########################################################
	/**
	 * 描画エレメントの取得(Mapパネル)
	 *
	 * ルートの場合は、自分自身を描画しない
	 * @param szPanelId パネル識別子
	 */
	public Vector createGobs(String szPanelId) {
	Vector gobs = new Vector();

/*
	*** 20020404 updateKeyAttribute() で更新するよう修正 ***
	// ページの正当性チェック
	// コンテナが、移動、削除されていた場合、
	// ドキュメント読み込み直後でコンテナが設定されていない場合はここで正す
	if ( ! ( checkContainer(szPanelId) ) ) {
		removeFromDocTree();
		return gobs;
	}
*/

	RidElementPage page = getContainer(0);
	GElement gob = page.getMainGob( szPanelId );
	if ( gob != null ) {
		ZPath path = page.getMapScenarioPath(szPanelId);
		GPath gpath = new GPath();
		gpath.setPath( path );

		Color col = getBackgroundColor();
		gpath.getStyle().setFillColor( new FColor( col ));

		gpath.setSelect(isSelect());
		gpath.setGobId("map");
		gpath.setContainer( this );
		gobs.add(gpath);

		ZRectangle rt = new ZRectangle(gpath.getBounds());
		ZPoint pt0 = rt.getCenter();

		// 次のシナリオアイテムへのパス描画
		RidElementScenarioItem item = getNextItem(szPanelId);
		boolean direct = true;
		while ( item != null ) {
			page = item.getContainer(0);
			gob  = page.getMainGob( szPanelId ) ;
			if ( gob != null ) {
				// 次のシナリオアイテムが見つかったので描画
				GLine line = new GLine();

				rt = new ZRectangle(gob.getBounds());
				ZPoint pt1 = rt.getCenter();
				line.getStyle().setStrokeColor( new FColor( col ) );
				line.setLine( new ZLine(pt0,pt1) );
				line.getStyle().getStroke().getWidth().set(20.0f);
				if ( !direct ) {
					float[] dash = new float[1];
					dash[0] = 10;
					line.getStyle().getStroke().getDashArray().set(dash);
				}
				gpath.addBackChild( line );
				break;
			}
			item = item.getNextItem(szPanelId);
			direct = false;
		}
	}

	return gobs;
	}

	/**
	 * コンテナのチェック
	 *
	 * @param szPanelId パネル識別子
	 */
/*
	*** 20020404 updateKeyAttribute() で更新するよう修正 ***
	public boolean checkContainer(String szPanelId) {
	String szKey   = getAttribute("Container");

	mContainer[0] = null;
	RidElement page = getContainer(0);
	if ( page == null ) {
		//ページが見つかりません
		return false;
	} else if ( page.getStatus().equals("remove") ) {
		//ページが削除されています
		return false;
	}
	return true;
	}
*/
	/**
	 * コンテナ先の更新
	 * @param oldValue 昔の値（nullの場合はunitが削除された）
	 * @param unit 更新されたユニット
	 */
	public void updateKeyAttribute( String oldValue, RidElement unit ) {
	String newValue = unit.getAttribute("Key");
	String checkTarget = oldValue;
	if ( checkTarget == null ) {
		checkTarget = newValue;
	}

	if ( getAttribute("Container").equals( checkTarget ) ) {
		if ( oldValue == null ) {
			// 削除
			removeFromDocTree();
		} else {
			// 名前の変更
			setAttribute("Container", newValue);
			mContainer[0] = (RidElementPage)unit;
		}
	}
	}

	//## ページへのリンク情報 #########################################
	/**
	 * 設定できるコンテナを探す。
	 * 見つかった場合、接続リストの1番目(一時領域)に保存する
	 * @param szPanelId パネル識別子
	 * @param pt        座標
	 * @param org       元のページ
	 */
	protected boolean findContainer(String szPanelId, ZPoint pt,RidElement org) {
	mContainer[1] = null;
	Enumeration elm = GobManager.elements(szPanelId,GobManager.ALL);
	while ( elm.hasMoreElements() ) {
		GElement item = (GElement)elm.nextElement();
		byte pos = item.getConnectMode(pt, this);
		if ( pos != 0 ) {
			RidElementPage container = (RidElementPage)item.getContainer();
			if ( container != null && container != org ) {
//				ZDebug.trace("find:"+pos);
				mContainer[1] = container;
				return true;
			}
		}
	}
	return false;
	}

	/**
	 * 検出済の接続できるコンテナをDOMに反映する
	 * @param szPanelId パネル識別子
	 */
	protected void updateContainer(String szPanelId) {
	// オブジェクトの設定
	// undo時にクリアされないので、nullに設定する
	mContainer[0] = mContainer[1] ;

	// DOMの設定
	String szKey = mContainer[0].getAttribute("Key");
//	ZDebug.trace("setKey:"+szKey);
	setAttribute("Container",szKey);

	mContainer[1] = null;
	}

	/**
	 * リンク対象の取得
	 * @param nIndex 位置キー
	 */
	protected RidElementPage getContainer(int nIndex) {
	if ( nIndex == 0 && mContainer[nIndex] == null ) {
		String szKey   = getAttribute("Container");

		// ポインタがセットされていない場合は、Topから検索
		RidDocumentSite doc = (RidDocumentSite)ZInstance.map().get( Rid.DOCUMENT_SITE );
		mContainer[nIndex] = (RidElementPage)doc.findChildElementInZone("PageUnit",szKey);
//		ZDebug.trace("find:"+szKey+" ... "+mContainer[nIndex]);
	}
	return mContainer[nIndex];
	}

	//## 兄弟情報 #####################################################
	/**
	 * 次のシナリオアイテムを探す。
	 * @param szPanelId パネルID
	 */
	protected RidElementScenarioItem getNextItem(String szPanelId) {
	Node node = getNextSibling();
	while ( node != null ) {
		if ( node instanceof RidElementScenarioItem ) {
			RidElementScenarioItem item = (RidElementScenarioItem)node;
			return (RidElementScenarioItem)node;
/*
			if ( item.checkContainer( szPanelId ) ) {
				return (RidElementScenarioItem)node;
			}
*/
		}
		node = node.getNextSibling();
	}
	return null;
	}

	//## アトリビュート################################################
	/**
	 * ページコンテナ
	 * コンテナは１つだが、2つ目の領域を編集用一時領域として利用する
	 */
	protected RidElementPage[] mContainer = new RidElementPage[2] ;
}
