/*
 * @(#)AccessCounts.java
 *
 * Copyright 2001 Nomura Research Institute, LTD. All rights reserved.
 *
 * RID-X : Array of access count
 *
 * @author  Intelligent Technology Inc.
 * @version 1.01 2001/10/29
 */
package jp.co.nri.rid.doc;

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

import jp.co.iti.fagot.geom.ZRectangle;

import jp.co.iti.fagot.util.ZString;
import jp.co.iti.fagot.util.ZDebug;
/**
 * アクセスカウントの配列
 */
public class AccessCounts {

	/**
	 * コンストラクタ
	 */
    public AccessCounts() {
    }

	/**
	 * コンストラクタ(初期値付)
	 * @param szCount AccessCountアトリビュート
	 */
    public AccessCounts(String szCount) {
	setArray( szCount, null );
    }

	/**
	 * コンストラクタ(初期値付)
	 * @param szCount AccessCountアトリビュート
	 * @param bLogList 有効データ配列
	 */
    public AccessCounts(String szCount, boolean[] bLogList) {
	setArray( szCount, bLogList );
    }

	/**
	 * 配列の設定
	 * @param szCount AccessCountアトリビュート
	 * @param bLogList 有効データ配列
	 */
	public void setArray( String szCount, boolean[] bLogList ) {
	mLogList = bLogList;
	mTotal = 0;
	String[] szArr = ZString.tokenize(szCount,",");
	mArray = new double[szArr.length] ;
	for ( int nAt=0 ; nAt<szArr.length ; nAt++ ) {
		double nTmp = ZString.parseDouble( szArr[nAt], 0 ) ;
		if ( bLogList == null ) {
			mTotal += nTmp ;
		} else if ( bLogList.length <= nAt ) {
			mTotal += nTmp ;
		} else if ( bLogList[nAt] ) {
			mTotal += nTmp ;
		}
		mArray[nAt] = nTmp ;
	}
	}

	/**
	 * 最大値のマージ
	 */
	public void margeMax( AccessCounts dst ) {
	int nSrcArrayCount = getArrayCount();
	int nDstArrayCount = dst.getArrayCount();
	int nAt = 0 ;
	// dstの方が配列が多い場合
	if ( nSrcArrayCount < nDstArrayCount ) {
		// 自分の配列を拡張したサイズの配列に格納する
		double[] nArray = new double[nDstArrayCount] ;
		for ( ; nAt<nSrcArrayCount ; nAt++ ) {
			nArray[nAt] = mArray[nAt] ;
		}
		for ( ; nAt<nDstArrayCount ; nAt++ ) {
			nArray[nAt] = 0 ;
		}
		mArray = nArray;
	}

	// dstのマージ
	for ( nAt=0 ; nAt<nDstArrayCount ; nAt++ ) {
		double nCnt = dst.getArrayData(nAt);
		if ( mArray[nAt] < nCnt ) {
			mArray[nAt] = nCnt ;
		}
	}

	// 合計値のマージ
	double nTotal = dst.getTotalCount();
	if ( mTotal < nTotal ) {
		mTotal = nTotal ;
	}
	}

	/**
	 * グラフの作成
	 * MapModelに登録されている基準データオブジェクトのみ呼ばれるメソッド
	 * @param rt  描画矩形
	 * @param acc 対象データ
	 */
	public ZRectangle[] createAccessRects( ZRectangle rt, AccessCounts dst ) {
//	ZDebug.trace("rtBase:"+rt);
	// グラフデータの抽出
	Vector vec = new Vector();
	int nAt    = 0;
	double nTotal = 0;
	double nCount = 0;
	int nDataCount = 0;
	int nDstCount = dst.getArrayCount();
	if ( mLogList != null ) {
		// 表示有無が設定されている場合は、設定されているところまで指示にしたがう
		for ( ; nAt < mLogList.length ; nAt++ ) {
			if ( mLogList[nAt] ) {
				if ( nAt < nDstCount ) {
					nCount = dst.getArrayData(nAt);
					vec.add( new Double(nCount) );
					if ( nCount > 0 ) {
						nTotal += nCount;
						nDataCount++;
					}
				} else {
					vec.add( new Double(0) );
				}
			}
		}
	}
	// 表示有無が設定されていない場合は、全て表示
	for ( ; nAt < nDstCount ; nAt++ ) {
		nCount = dst.getArrayData(nAt);
		vec.add( new Double(nCount) );
		if ( nCount > 0 ) {
			nTotal += nCount;
			nDataCount++;
		}
	}
	// データがなく、他のページにデータがある場合０を追加
	for ( ; nAt < getArrayCount() ; nAt++ ) {
		vec.add( new Double(0) );
	}

	ZRectangle[] rtList = null;
	if ( mLogType.equals("join") ) {
		// 結合ビューの場合は矩形１つ
		if ( nTotal != 0 ) {
			double dHeight = rt.getHeight()*nTotal/mMax ;
			rtList = new ZRectangle[1] ;
			rtList[0] = new ZRectangle( rt.getX(), rt.getY()+rt.getHeight()-dHeight,
										rt.getWidth(), dHeight);
		}
	} else if ( nDataCount > 0 ) {
		rtList = new ZRectangle[nDataCount] ;
		Enumeration elm = vec.elements();
		nAt = 0;
		double dX = rt.getX();
		double dY = rt.getY();
		double dW = rt.getWidth();
		double dH = rt.getHeight();
		// 積み上げ式の場合のデータ
		double dB = 0;
		// 並列の場合のデータ
		int nCnt  = 0;
		int nSize = vec.size();
		while ( elm.hasMoreElements() ) {
			Double val = (Double)elm.nextElement();
			double nVal = val.doubleValue();
			if ( nVal > 0 ) {
				double dHeight = dH*nVal/mMax ;
				if ( !mLogType.equals("parallel") ) {
					// 積み上げ式の場合
					rtList[nAt] = new ZRectangle( dX, dY+dH-dB-dHeight, dW, dHeight);
//					ZDebug.trace("rt:"+rtList[nAt]);
					dB += dHeight;
				} else {
					// 並列の場合
					rtList[nAt] = new ZRectangle( dX+(dW/nSize)*nCnt, dY+dH-dHeight, dW/nSize, dHeight);
				}
				nAt++;
			}
			nCnt++;
		}
	}

	return rtList;
	}

	//## 値 ###########################################################
	/**
	 * 最大値の計算
	 */
	public void calcMaxCount() {
	if ( !mLogType.equals("parallel") ) {
		mMax = mTotal ;
	} else {
		mMax = 0;
		for ( int nAt=0 ; nAt < mArray.length ; nAt++ ) {
			if ( mLogList==null || mLogList.length<=nAt || mLogList[nAt] ) {
				if ( mMax == 0 ) {
					mMax = mArray[nAt] ;
				} else if ( mMax < mArray[nAt] ) {
					mMax = mArray[nAt] ;
				}
			}
		}
	}
	if ( mMax == 0 ) {
		mMax = 1000;
	}
	}

	//## 値 ###########################################################
	/**
	 * 合計値の取得
	 */
	public double getTotalCount() {
	return mTotal;
	}

	/**
	 * 配列長の取得
	 */
	public int getArrayCount() {
	if ( mArray == null ) {
		return 0;
	}
	return mArray.length;
	}

	/**
	 * 配列データの取得
	 * @param nAt 配列添え字
	 */
	public double getArrayData( int nAt ) {
	if ( mArray == null || mArray.length <= nAt ) {
		return 0;
	}
	return mArray[nAt];
	}

	/**
	 * ログタイプの設定
	 * @param szLogType ログタイプ { "serial" | "parallel" | "join" }
	 */
	public void setLogType( String szLogType ) {
	mLogType = szLogType ;
	}

	//## アトリビュート ###############################################
	/**
	 * トータル
	 */
	protected double mTotal = 0;

	/**
	 * 最大値
	 */
	protected double mMax = 1000;

	/**
	 * アクセスカウントの配列
	 */
	protected double[] mArray = null;

	/**
	 * アクセスカウント表示有無配列
	 */
	protected boolean[] mLogList = null;

	/**
	 * アクセスログのタイプ
	 */
	protected String mLogType = "";
}
