/*
 * 作成日: 2003/12/29
 *
 */

package openolap.viewer;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import openolap.viewer.common.Constants;

/**
 */
public abstract class Edge implements Serializable {

	final private ArrayList axisList;	// 軸リスト

	// ********** コンストラクタ **********

	public Edge(ArrayList axisList){
		this.axisList = axisList;
	}

	public Edge(Axis axis) {
		this.axisList = new ArrayList();
		this.axisList.add(axis);
	}


	// ********** abstract メソッド **********

	public abstract String getPosition();

	// ********** 静的メソッド **********

	public static Edge getTheEdge(String position, ArrayList edgeList) {
		if ((position == null) || (edgeList == null)) { throw new IllegalArgumentException();}
		if (edgeList.size() < 2) { throw new IllegalStateException();}

		if (position.equals(Constants.Col)) {
			return (Edge)edgeList.get(0);
		} else if (position.equals(Constants.Row)) {
			return (Edge)edgeList.get(1);
		} else if (position.equals(Constants.Page)) {
			return (Edge)edgeList.get(2);
		} else {
			throw new IllegalStateException();
		}
	}


	// ********** メソッド **********

	public boolean hasThisAxis(Axis oAxis){
		if (oAxis == null){ return false; }
		Iterator it = this.getAxisList().iterator();
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			if (axis.getId() == oAxis.getId()) {
				return true;
			}
		}
		return false;		
	}
	public boolean hasThisAxis(String axisId) {
		if (axisList == null){ return false; }
		Iterator it = this.getAxisList().iterator();
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			if (axis.getId() == axisId) {
				return true;
			}
		}
		return false;
	}

	// エッジ内の次段に配置された軸のメンバ数(セレクタで除外されているものは含まない)を返す
	// Dimensionの持つメンバリストは一時的に使用される情報であることに注意。
	public Integer getNextAxisMemberNums(Axis axis) {
		if (axis == null) { throw new IllegalArgumentException(); }
		if (this.hasThisAxis(axis) == false) { throw new IllegalArgumentException(); }
		Iterator it = this.getAxisList().iterator();
		int i = 0;
		while (it.hasNext()) {
			Axis tmpAxis = (Axis) it.next();
			if (axis.getId().equals(tmpAxis.getId())) {
				if(i == (this.getAxisList().size()-1)) { // 最終段が指定された場合
					return null;
				} else {

					Axis nextAxis = (Axis)it.next();
//System.out.println("nextAxis:" + nextAxis.getName());
					Integer nextAxisMemberNums = null;
					if (nextAxis.isUsedSelecter()) {// セレクタによる絞込み中
						Iterator nextAxisMemIt = nextAxis.getAxisMemberList().iterator();
						int count = 0;
						while (nextAxisMemIt.hasNext()) {
							AxisMember axisMember = (AxisMember) nextAxisMemIt.next();
							if (axisMember.isSelected()){
								count++;
							}
						}
						nextAxisMemberNums = new Integer(count);
					} else { // セレクタによる絞込み中ではない

						nextAxisMemberNums = new Integer( nextAxis.getAxisMemberList().size());
					}

					return nextAxisMemberNums;
				}
			}
			i++;
		}
		return null;
	}

	// エッジ内の次段以降に配置された軸のメンバ数(セレクタで除外されているものは含まない)の積を返す
	// Dimensionの持つメンバリストは一時的に使用される情報であることに注意。
	public Integer getNextAxesMembersComboNums(Axis axis) {
		if (axis == null) { throw new IllegalArgumentException(); }
		if (this.hasThisAxis(axis) == false) { throw new IllegalArgumentException(); }
		Iterator it = this.getAxisList().iterator();
		int i = 0;
		while (it.hasNext()) {
			Axis tmpAxis = (Axis) it.next();
			if (axis.getId().equals(tmpAxis.getId())) {
				if(i == (this.getAxisList().size()-1)) { // 最終段が指定された場合
					return null;
				} else {

//System.out.println("nextAxis:" + nextAxis.getName());
					int nextAxesComboNums = 1;
					while (it.hasNext()) {
						Axis nextAxis = (Axis)it.next();

						if (nextAxis.isUsedSelecter()) {// セレクタによる絞込み中
							Iterator nextAxisMemIt = nextAxis.getAxisMemberList().iterator();
							int count = 0;
							while (nextAxisMemIt.hasNext()) {
								AxisMember axisMember = (AxisMember) nextAxisMemIt.next();
								if (axisMember.isSelected()){
									count++;
								}
							}
							nextAxesComboNums = nextAxesComboNums * count;
						} else { // セレクタによる絞込み中ではない
	
							nextAxesComboNums = nextAxesComboNums * nextAxis.getAxisMemberList().size();
						}
					}

					return new Integer(nextAxesComboNums);
				}
			}
			i++;
		}
		return null;
	}


	// エッジ内の指定された軸より前に配置された軸のメンバ数(セレクタで除外されているものは含まない)の積を求める
	// Dimensionの持つメンバリストは一時的に使用される情報であることに注意。
	public Integer getBeforeAxesMembersComboNums(Axis axis) {
		if (axis == null) { throw new IllegalArgumentException(); }
		if (this.hasThisAxis(axis) == false) { throw new IllegalArgumentException(); }
		Iterator it = this.getAxisList().iterator();
		ArrayList beforeAxisList = new ArrayList();
		while (it.hasNext()) {
			Axis tmpAxis = (Axis) it.next();
			if (axis.getId().equals(tmpAxis.getId())) {
				if (beforeAxisList.size() == 0) {// 0段目が指定された場合
					return null;
				} else {
					int beforeAxesComboNums = 1;

					Iterator beforeAxisIt = beforeAxisList.iterator();
					while (beforeAxisIt.hasNext()) {
						Axis beforeAxis = (Axis) beforeAxisIt.next();
						if(beforeAxis.isUsedSelecter()) { // セレクタによる絞込み中
							Iterator beforeAxisMemIt = beforeAxis.getAxisMemberList().iterator();
							int count = 0;
							while (beforeAxisMemIt.hasNext()) {
								AxisMember axisMember = (AxisMember) beforeAxisMemIt.next();
								if (axisMember.isSelected()) {
									count++;
								}
							}
							beforeAxesComboNums = beforeAxesComboNums * count;

						} else {// セレクタによる絞込み中ではない
							beforeAxesComboNums = beforeAxesComboNums * beforeAxis.getAxisMemberList().size();
						}
					}
					return new Integer(beforeAxesComboNums);
				}
			}
			beforeAxisList.add(tmpAxis);
		}
		return null;
	}


	public int getAxisIndexInEdge(Axis oAxis){
		if (oAxis == null){ return -1; }
		Iterator it = this.getAxisList().iterator();
		int i = 0;
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			if (axis.getId() == oAxis.getId()) {
				return i;
			}
			i++;
		}
		return -1;
	}
	public int getAxisIndexInEdge(String axisId){
		if (axisId == null) { return -1; }
		Iterator it = this.getAxisList().iterator();
		int i = 0;
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			if (axis.getId() == axisId) {
				return i;
			}
			i++;
		}
		return -1;
	}

	public boolean investigateTimeDimension() {
		Iterator it = this.axisList.iterator();
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			
			if(!axis.isMeasure()) {
				Dimension dim = (Dimension)axis;
				if(dim.isTimeDimension()){
					return true;
				}
			}
		}
		return false;
	}

	public Measure getMeasure() {
		Iterator it = this.axisList.iterator();
		while (it.hasNext()) {
			Axis axis = (Axis) it.next();
			
			if(axis.isMeasure()) {
				return (Measure)axis;
			}
		}	
		return null;
	}


	public void addAxis(Axis axis) {
		if (axis == null){ throw new IllegalArgumentException(); }

		this.axisList.add(axis);
	}

	public void clearAxis() {
		this.axisList.clear();
	}

	// ********** Getter メソッド **********

	public ArrayList getAxisList() {
		return axisList;
	}

}
