/*
 * 作成日: 2003/12/29
 */
package openolap.viewer;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;

import openolap.viewer.common.Constants;
import openolap.viewer.common.Messages;
import openolap.viewer.controller.RequestHelper;
import openolap.viewer.dao.DAOFactory;
import openolap.viewer.dao.DimensionMemberDAO;
import openolap.viewer.dao.ReportDAO;

/**
 */
public class Report implements Serializable {

	// ********** インスタンス変数 **********
	private String reportName = null;			// レポート名
	final private String reportID;			// レポートID
	private String parentID;					// 親ID(レポートを格納するフォルダのID)
	final private Cube cube;					// キューブ
	final private ArrayList edgeList;			// エッジリスト
	final private ArrayList colorList;		// 色情報リスト
	final private boolean hasTimeDim;		// 時間次元を持つか
	private boolean isNewReport = false;		// 新規レポート(true)か、既存レポート(false)か

	// ********** コンストラクタ **********
	public Report(String reportID, String reportName, Cube cube, ArrayList edgeList, ArrayList colorList, boolean hasTimeDim){
		this.reportID = reportID;
		this.reportName = reportName;
		this.parentID = null;
		this.cube = cube;
		this.edgeList = edgeList;
		this.colorList = colorList;
		this.hasTimeDim = hasTimeDim;
	}


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

	public static boolean investigateTimeDimension(ArrayList edgeList) {
		Edge col = (Edge)Edge.getTheEdge("COL",edgeList);
		Edge row = (Edge)Edge.getTheEdge("ROW",edgeList);
		Edge page = (Edge)Edge.getTheEdge("PAGE",edgeList);

		return (col.investigateTimeDimension() || row.investigateTimeDimension() || page.investigateTimeDimension());
	}


	public static ArrayList initializeEdge(ArrayList dimList, Measure measure) {
		if ( (dimList == null) || (measure == null) ) { throw new IllegalArgumentException(); }
		if (dimList.size() < 1) { throw new IllegalArgumentException(); }

		Col col = null;
		Row row = null;
		Page page = null;
		ArrayList pageAxisList = new ArrayList();

		dimList.add(measure);

		col = new Col((Axis)dimList.get(0));
		row = new Row((Axis)dimList.get(1));

		if ( dimList.size()-2 > 0 ) { // ディメンションをふたつ以上持つ（ページエッジが軸を持つ）場合
			for(int i=0; i<(dimList.size()-2); i++){
				pageAxisList.add(dimList.get(i+2));
				page = new Page(pageAxisList);
			}
		} else {	// ページエッジに軸が存在しない場合、空のArrayListを持たせる
			page = new Page(new ArrayList());
		}

		ArrayList edgeList = new ArrayList();
		edgeList.add(col);
		edgeList.add(row);
		edgeList.add(page);

		return edgeList;
	}

	public static String getInitialReportName() {
		return Messages.getString("Report.tempInitialReportName"); //$NON-NLS-1$
	}

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

	/**
	 * Reportオブジェクトの行、列エッジに配置されたディメンションに、メンバーオブジェクトをセットする
	 * @param helper
	 * @param report
	 */
	public void setSelectedCOLROWDimensionMembers(RequestHelper helper, Report report, Connection conn) throws SQLException {

		DimensionMemberDAO dimMemberDAO = DAOFactory.getDAOFactory().getDimensionMemberDAO(conn);

		Iterator it = report.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			Iterator it2 = edge.getAxisList().iterator();

			if (edge.getPosition().equals(Constants.Page)) {
				continue;
			}

			int i = 0;
			while (it2.hasNext()) {
				Axis axis = (Axis) it2.next();
				Dimension dim = null;
				if(axis instanceof Dimension) {
					dim = (Dimension) axis;
				} else {
					i++;
					continue;
				}

				String selectedMemberList = "";
				if (edge.getPosition().equals(Constants.Col)) {
					selectedMemberList = "'," + helper.getRequest().getSession().getAttribute("viewCol" + i + "KeyList_hidden") + ",'";
				} else if (edge.getPosition().equals(Constants.Row)) {
					selectedMemberList = "'," + helper.getRequest().getSession().getAttribute("viewRow" + i + "KeyList_hidden") + ",'";
				}

				ArrayList dimMemberList = dimMemberDAO.selectDimensionMembers(dim, null, null, null, selectedMemberList);
				dim.clearAxisMember();
				dim.addAllAxisMember(dimMemberList);

//stem.out.println(dim.getName() + "," + dimMemberList.size());

				i++;
			}
		}

//System.out.println(((Axis)((Edge)report.getEdgeList().get(0)).getAxisList().get(0)).getAxisMemberList().size());
//System.out.println(((Axis)((Edge)report.getEdgeList().get(1)).getAxisList().get(0)).getAxisMemberList().size());

	}


	// ディメンションからメンバーを削除する
	public void clearDimensionMembers() {
		
		Iterator it = edgeList.iterator();
		int dimCounter = 0;
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			Iterator it2 = edge.getAxisList().iterator();
			while (it2.hasNext()) {
				Axis axis = (Axis) it2.next();
				if(!axis.isMeasure()){
					axis.clearAxisMember();
				}
			}
		}		
		
	}



	public int getTotalDimensionNumber(){

		Iterator it = edgeList.iterator();
		int dimCounter = 0;
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			Iterator it2 = edge.getAxisList().iterator();
			while (it2.hasNext()) {
				Axis axis = (Axis) it2.next();
				if(!axis.isMeasure()){
					dimCounter++;
				}
			}
		}

		return dimCounter;
	}

	public int getTotalMeasureMemberNumber(){
		ArrayList measureMemberList = this.getMeasure().getAxisMemberList();
		return measureMemberList.size();
	}

	public Edge getEdgeByType(String edgeType) {
		Iterator it = edgeList.iterator();		
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if (edge.getPosition().equals(edgeType)){
				return edge;
			}
		}
		return null;
	}


	public Measure getMeasure() {
		Iterator it = this.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if(edge.getMeasure() != null) {
				return edge.getMeasure();
			}
		}
		throw new IllegalStateException();
	}

	public Axis getAxisByID(String sourceID) {
		Iterator it = this.getEdgeList().iterator();		
		while (it.hasNext()) {		
			Edge edge = (Edge) it.next();
			Iterator axisIt = edge.getAxisList().iterator();

//System.out.println("edgePosition, axisSize:" + edge.getPosition() + "," + edge.getAxisList().size());

			while (axisIt.hasNext()) {
				Axis axis = (Axis) axisIt.next();

//System.out.println("Report axis.getId():" + axis.getId());

				if(axis.getId().equals(sourceID)) {
					return axis;
				}
			}
		}		
		return null;
	}

	// AxisId の昇順でAxisオブジェクトを取得する

	public ArrayList getAxilOrderByID() {
		ArrayList axisList = new ArrayList();

		TreeMap axisIdObjMap = new TreeMap();
		Iterator it = this.getEdgeList().iterator();		
		while (it.hasNext()) {		
			Edge edge = (Edge) it.next();
			Iterator axisIt = edge.getAxisList().iterator();

			while (axisIt.hasNext()) {
				Axis axis = (Axis) axisIt.next();
				axisIdObjMap.put(Integer.decode(axis.getId()), axis);
			}
		}		

		Iterator axisIt = axisIdObjMap.keySet().iterator();
		while (axisIt.hasNext()) {
			Integer axisID = (Integer) axisIt.next();
			Axis axis = (Axis) axisIdObjMap.get(axisID) ;
			axisList.add(axis);
		}

		return axisList;		
	}

	public String getThisAxisPosition(Axis oAxis){
		if (oAxis == null){ return null; }
		Iterator it = this.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if (edge.hasThisAxis(oAxis)){
				return edge.getPosition();
			}
		}
		return null;			
	}
	public String getThisAxisPosition(String id){
		if (id == null){ return null; }
		Iterator it = this.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if (edge.hasThisAxis(id)){
				return edge.getPosition();
			}
		}
		return null;			
	}
	public boolean isInCol(Axis oAxis){
		if (oAxis == null){ return false; }
		if (this.getThisAxisPosition(oAxis).equals("COL")){
			return true;
		} else {
			return false;
		}
	}
	public boolean isInCol(String axisId){
		if (axisId == null){ return false; }
		if (this.getThisAxisPosition(axisId).equals("COL")){
			return true;
		} else {
			return false;
		}
	}
	public boolean isInRow(Axis oAxis){
		if (oAxis == null){ return false; }
		if (this.getThisAxisPosition(oAxis).equals("ROW")){
			return true;
		} else {
			return false;
		}
	}
	public boolean isInRow(String axisId){
		if (axisId == null){ return false; }
		if (this.getThisAxisPosition(axisId).equals("ROW")){
			return true;
		} else {
			return false;
		}
	}
	public boolean isInPage(Axis oAxis){
		if (oAxis == null){ return false; }
		if (this.getThisAxisPosition(oAxis).equals("PAGE")){
			return true;
		} else {
			return false;
		}
	}
	public boolean isInPage(String axisId){
		if (axisId == null){ return false; }
		if (this.getThisAxisPosition(axisId).equals("PAGE")){
			return true;
		} else {
			return false;
		}
	}

	public int getHieIndex(Axis oAxis){
		if (oAxis == null){ return -1; }
		Iterator it = this.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if (edge.getAxisIndexInEdge(oAxis) != -1){
				return edge.getAxisIndexInEdge(oAxis);
			}
		}
		return 0;
	}
	public int getHieIndex(String axisID){
		if (axisID == null){ return -1; }
		Iterator it = this.getEdgeList().iterator();
		while (it.hasNext()) {
			Edge edge = (Edge) it.next();
			if (edge.getAxisIndexInEdge(axisID) != -1){
				return edge.getAxisIndexInEdge(axisID);
			}
		}
		return -1;
	}


	/**
	 * 指定されたエッジに配置された軸メンバの組み合わせ数
	 * @param string
	 * @return
	 */
	public int getAxisMeberComboNum(String edgeName) {
		if ( (!Constants.Col.equals(edgeName)) && (!Constants.Row.equals(edgeName)) && (!Constants.Page.equals(edgeName)) ) {
			throw new IllegalStateException();
		}

		int totalNumber = 1;

		ArrayList edgeAxesList = this.getEdgeByType(Constants.Col).getAxisList();
		Iterator iter = edgeAxesList.iterator();
		while (iter.hasNext()) {
			Axis axis = (Axis) iter.next();
			totalNumber = totalNumber * (axis.getAxisMemberList().size());
		} 

		return totalNumber;
	}


	public void addColor(Color color) {
		if(color == null) { throw new IllegalArgumentException(); }
		
		this.colorList.add(color);
	}

	public void addColor(ArrayList colorList) {
		if(colorList == null) { throw new IllegalArgumentException(); }

		Iterator it = colorList.iterator();
		while (it.hasNext()) {
			Color color = (Color) it.next();
			this.colorList.add(color);
		}
	}

	public void clearColorList() {
		this.colorList.clear();
		
	}

	public ArrayList getHeaderColorList() {
		ArrayList headerColorList = new ArrayList();
		Iterator it = this.colorList.iterator();
		while (it.hasNext()) {
			Color color = (Color) it.next();
			if(color.isHeader()){
				headerColorList.add(color);
			}
		}
		return headerColorList;
	}

	public ArrayList getSpreadColorList() {
		ArrayList spreadColorList = new ArrayList();
		Iterator it = this.colorList.iterator();
		while (it.hasNext()) {
			Color color = (Color) it.next();
			if(!color.isHeader()){
				spreadColorList.add(color);
			}
		}
		return spreadColorList;
	}


	public void saveReport(Connection conn) throws SQLException {
		DAOFactory daoFactory = DAOFactory.getDAOFactory();

		ReportDAO reportDAO = daoFactory.getReportDAO(conn);
		reportDAO.saveReport(this, conn);
	}


	// ********** Setter メソッド **********
	public void setReportName(String string) {
		reportName = string;
	}
	public void setParentID(String string) {
		parentID = string;
	}
	public void setNewReport(boolean b) {
		isNewReport = b;
	}

	// ********** Getter メソッド **********
	public String getReportName() {
		return reportName;
	}
	public String getReportID() {
		return reportID;
	}
	public String getParentID() {
		return parentID;
	}
	public Cube getCube() {
		return cube;
	}
	public ArrayList getEdgeList() {
		return edgeList;
	}
	public ArrayList getColorList() {
		return colorList;
	}
	public boolean hasTimeDim() {
		return hasTimeDim;
	}
	public boolean isNewReport() {
		return isNewReport;
	}

}
