/*
 * @(#)MapMinorTree.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : Map Calc Minor Tree
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/10/29
 */
package jp.co.nri.rid.doc;

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

import jp.co.iti.fagot.util.ZDebug;
/**
 * Map Viewにおける子ノード間の距離演算クラス
 */
public class MapMinorTree {

	/**
	 * コンストラクタ
	 */
    public MapMinorTree() {
	mVector = new Vector();
    }

	/**
	 * 階層の追加
	 */
	public void add( double dMinor ) {
	mVector.add( 0, new MinMax( dMinor ) );
	}

	/**
	 * 階層のマージ
	 * @param src マージ対象のMapTree
	 */
	public void marge( MapMinorTree src ) {
	Vector marge = new Vector();
	Enumeration myElm  = mVector.elements();
	Enumeration srcElm = src.getVector().elements();
	while ( myElm.hasMoreElements() ) {
		MinMax myData = (MinMax)myElm.nextElement();
		if ( srcElm.hasMoreElements() ) {
			MinMax srcData = (MinMax)srcElm.nextElement();
			MinMax newData = new MinMax( Math.min( srcData.getMin(),myData.getMin() ),
										 Math.max( srcData.getMax(),myData.getMax() ) );
			marge.add(newData);
		} else {
			marge.add(myData);
		}
	}
	while ( srcElm.hasMoreElements() ) {
		MinMax srcData = (MinMax)srcElm.nextElement();
		marge.add(srcData);
	}
	mVector = marge;
	
	// 最終インデントの引継ぎ
	setLastIndent( src.getLastIndent() ) ;
	}

	/**
	 * 階層間の距離の計算
	 * @param src 計算対象のMapTree
	 * srcの方が後ろにあることを前提とする
	 * @return 距離
	 */
	public double distance( MapMinorTree src ) {
//	ZDebug.trace();
//	ZDebug.trace("   mytree:"+toString());
//	ZDebug.trace("  srctree:"+src.toString());
	Enumeration myElm  = mVector.elements();
	Enumeration srcElm = src.getVector().elements();

	MinMax myData = (MinMax)myElm.nextElement();
	MinMax srcData = (MinMax)srcElm.nextElement();

//	double dist = Math.min( Math.abs(myData.getMin()-srcData.getMax()),
//							Math.abs(myData.getMax()-srcData.getMin()) );
	double dist = srcData.getMin()-myData.getMax();

	while ( myElm.hasMoreElements() ) {
		myData = (MinMax)myElm.nextElement();
		if ( srcElm.hasMoreElements() ) {
			srcData = (MinMax)srcElm.nextElement();
//			double dist2 = Math.min( Math.abs(myData.getMin()-srcData.getMax()),
//									 Math.abs(myData.getMax()-srcData.getMin()) );
			double dist2 = srcData.getMin()-myData.getMax();
			if ( dist2 < dist ) {
				dist = dist2;
			}
		} else {
			break;
		}
	}
//	ZDebug.trace(" distance:"+dist);
	return dist;
	}

	/**
	 * 直接の子供の半分の値
	 */
	public double getChildHarf() {
	Enumeration elm = mVector.elements();
	MinMax data = (MinMax)elm.nextElement();
	return (data.getMax()+data.getMin())/2;
	}

	/**
	 * 最大Minor番号の取得
	 * @return 最大Minor番号
	 */
	public double getMaxMinor() {
	Enumeration elm = mVector.elements();
	MinMax data = (MinMax)elm.nextElement();
	double dMax = data.getMax();
	while ( elm.hasMoreElements() ) {
		data = (MinMax)elm.nextElement();
		if ( dMax < data.getMax() ) {
			dMax = data.getMax();
		}
	}
	return dMax;
	}

	/**
	 * 最小Minor番号の取得
	 * @return 最小Minor番号
	 */
	public double getMinMinor() {
	Enumeration elm = mVector.elements();
	MinMax data = (MinMax)elm.nextElement();
	double dMin = data.getMin();
	while ( elm.hasMoreElements() ) {
		data = (MinMax)elm.nextElement();
		if ( dMin < data.getMin() ) {
			dMin = data.getMin();
		}
	}
	return dMin;
	}

	//## 値 ###########################################################
	/**
	 * 階層Vectorの取得
	 */
	public Vector getVector() {
	return mVector;
	}

	/**
	 * 階層の深さの取得
	 */
	public int getDepth() {
	return mVector.size();
	}

	/**
	 * 最終インデントの取得
	 */
	public boolean getLastIndent() {
	return mLastIndent;
	}

	/**
	 * 最終インデントの設定
	 */
	public void setLastIndent(boolean bIndent) {
	mLastIndent = bIndent ;
	}

	/**
	 * 文字列化
	 */
	public String toString() {
	String szRet = "MapTree";
	Enumeration elm = mVector.elements();
	while( elm.hasMoreElements() ) {
		MinMax data = ( MinMax ) elm.nextElement();
		szRet += ":" + data.getMin() + "," + data.getMax();
	}
	return szRet;
	}

	//## アトリビュート ###############################################
	/**
	 * 階層データ
	 */
	protected Vector mVector = null;

	/**
	 * 最終エレメントのインデント
	 */
	protected boolean mLastIndent = false;

	//## サブクラス：最小最大値 #######################################
	/**
	 * 各階層の最小、最大Minor番号を保持するクラス
	 */
	public class MinMax {
	/**
	 * コンストラクタ：初期設定用
	 * @param dValue 最小値=最大値
	 */
    public MinMax(double dValue) {
	mMin = dValue;
	mMax = dValue;
    }

	/**
	 * コンストラクタ
	 * @param dMin 最小値
	 * @param dMax 最大値
	 */
    public MinMax(double dMax, double dMin) {
	mMin = dMax;
	mMax = dMin;
    }

	/**
	 * 最大値の取得
	 */
    public double getMax() {
	return mMax;
    }

	/**
	 * 最小値の取得
	 */
    public double getMin() {
	return mMin;
    }

	//## アトリビュート ###############################################
	/**
	 * 最小値
	 */
	protected double mMin = 0;

	/**
	 * 最大値
	 */
	protected double mMax = 0;
	}

}
