/* $Id: ConcurrentLayerManager.java,v 1.2 2007/12/11 09:54:58 nito Exp $
 * 
 * Copyright (c)ARGO 21, Corporation. 2005, 2006.  All rights reserved.
 * 
 * This file is part of Nautica Workflow.
 * 
 *  Nautica Workflow is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 * 
 *  Nautica Workflow is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with Nautica Workflow; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *  
 */
package jp.co.argo21.nautica.tool.wfd;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import jp.co.argo21.nautica.commons.util.StringUtils;
import jp.co.argo21.nautica.tool.wfd.element.ActivityElement;

/**
 * 同期階層を管理するマネージャ
 * 
 * @author  Norihiro Itoh(ARGO 21 Corp.)
 * @version $Revision: 1.2 $
 * @since   Nautica Workflow 1.0
 */
public class ConcurrentLayerManager
{
	//内包される同期階層のリスト
	private List<ConcurrentLayer> subLayers = new ArrayList<ConcurrentLayer>();
	//このレイヤーに所属するアクティビティのリスト
	private List<ActivityElement> activities = new ArrayList<ActivityElement>();

	/**
	 * 同期階層マネージャを生成する。
	 */
	public ConcurrentLayerManager()
	{
	}

	/**
	 * 同期階層を初期化する。
	 * 
	 * @param activities	アクティビティ一覧
	 */
	public void initConcurrentLayer(List<ActivityElement> activities)
	{
		Map<String, ConcurrentLayer> layers = new Hashtable<String, ConcurrentLayer>();

		for (ActivityElement act : activities) {
			if (act.getType().equals(ActivityElement.CONCUR_START)) {
				ConcurrentLayer l = new ConcurrentLayer();
				l.setStartElement(act);
				layers.put(act.getBlockID(), l);
			}
		}

		for (ActivityElement act : activities) {
			if (act.getType().equals(ActivityElement.CONCUR_START)) {
			} else if (act.getType().equals(ActivityElement.CONCUR_END)) {
				ConcurrentLayer l = (ConcurrentLayer)layers.get(act.getBlockID());
				l.setEndElement(act);
				String parentID = act.getParentBID();
				if (StringUtils.checkNull(parentID)) {
					addLayer(l);
				} else {
					ConcurrentLayer pl = (ConcurrentLayer)layers.get(parentID);
					l.setParentLayer(pl);
					pl.addLayer(l);
				}
			} else {
				String affID = act.getAffiliateBID();
				if (StringUtils.checkNull(affID)) {
				} else {
					ConcurrentLayer al = (ConcurrentLayer)layers.get(affID);
					al.addLayerElement(act);
				}
			}
		}
	}

	/**
	 * 階層IDを返す。
	 * 
	 * @return	階層ID
	 */
	public String getLayerID()
	{
		return null;
	}
	
	/**
	 * 階層にアクティビティを追加する。
	 * 
	 * @param elem	アクティビティ
	 */
	public void addLayerElement(ActivityElement elem)
	{
		if (elem == null) return;
		activities.add(elem);
	}

	/**
	 * 階層からアクティビティを削除する。
	 * 
	 * @param elem	アクティビティ
	 */	
	public void removeLayerElement(ActivityElement elem)
	{
		if (elem == null) return;
		if (activities.contains(elem)) {
			activities.remove(elem);
		} else {
			for (ConcurrentLayer layer : subLayers) {
				layer.removeLayerElement(elem);
			}
		}
	}

	/**
	 * 
	 * 
	 * @param layer
	 */	
	public void addLayer(ConcurrentLayer layer)
	{
		if (layer == null) return;
		
		addLayerElement(layer.getStartElement());
		addLayerElement(layer.getEndElement());
		subLayers.add(layer);
	}

	/**
	 * 同期階層を追加する。
	 * 
	 * @param l	同期階層
	 */	
	public void removeLayer(ConcurrentLayer l)
	{
		if (l == null) return;
		if (subLayers.contains(l)) {
			removeLayerElement(l.getStartElement());
			removeLayerElement(l.getEndElement());
			l.clearParentLayer();
			subLayers.remove(l);
		} else {
			for (ConcurrentLayer layer : subLayers) {
				layer.removeLayer(l);
			}
		}
	}

	/**
	 * 同期階層を収集する。
	 * 
	 * @param list	同期階層を格納する一覧
	 */	
	public void collectAllLayerElement(List<ActivityElement> list)
	{
		for (ConcurrentLayer layer : subLayers) {
			layer.collectAllLayerElement(list);
		}

		for (ActivityElement act : activities) {
			if (list.contains(act) == false) list.add(act);
		}
	}
	
	/**
	 * 受け入れ可能な同期レイヤーを返す。
	 * 
	 * @param lx 論理X座標
	 * @param ly 論理Y座標
	 * @return 同期階層
	 */
	public ConcurrentLayer getReceivableLayer(int lx, int ly)
	{
		for (ConcurrentLayer layer : subLayers) {
			ConcurrentLayer rLayer = layer.getReceivableLayer(lx, ly);
			if (rLayer != null) return rLayer;
		}
		return null;
	}

	/**
	 * 指定されたアクティビティが所属する同期階層を返す。
	 * 
	 * @param elem	アクティビティ
	 * @return	同期階層
	 */	
	public ConcurrentLayer getContainLayer(ActivityElement elem)
	{
		for (ConcurrentLayer layer : subLayers) {
			ConcurrentLayer cLayer = layer.getContainLayer(elem);
			if (cLayer != null) return cLayer;
		}
		return null;
	}

	/**
	 * この階層の並行処理開始アクティビティを返す。
	 * 
	 * @return	並行処理開始アクティビティ
	 */
	public ActivityElement getStartElement()
	{
		return null;
	}

	/**
	 * この階層の並行処理終了アクティビティを返す。
	 * 
	 * @return	並行処理終了アクティビティ
	 */
	public ActivityElement getEndElement()
	{
		return null;
	}

	/**
	 * 親の同期階層を返す。
	 * 
	 * @return	同期階層
	 */
	public ConcurrentLayer getParentLayer()
	{
		return null;
	}

	/**
	 * 再配置可能な上部位置を返す。
	 * 
	 * @return	論理座標
	 */	
	public Point getMinimumUpperPoint()
	{
		int x = Integer.MAX_VALUE;
		int y = Integer.MAX_VALUE;
		return new Point(x, y);
	}

	/**
	 * 再配置可能な下部位置を返す。
	 * 
	 * @return	論理座標
	 */	
	public Point getMinimumLowerPoint()
	{
		int x = 0;
		int y = 0;
		return new Point(x, y);
	}

	/**
	 * 同期階層の背景を描画する。
	 * 
	 * @param g	描画対象グラフィックス
	 * @param c	描画色
	 * @param grid	単位幅
	 */	
	public void paintLayerBackgroud(Graphics g, Color c, int grid)
	{
		for (ConcurrentLayer layer : subLayers) {
			layer.paintLayerBackgroud(g, c, grid);
		}
	}

	/**
	 * 同期階層の枠を描画する。
	 * 
	 * @param g	描画対象グラフィックス
	 * @param c	描画色
	 * @param grid	単位幅
	 */
	public void paintLayerBorder(Graphics g, Color c, int grid)
	{
		for (ConcurrentLayer layer : subLayers) {
			layer.paintLayerBorder(g, c, grid);
		}
	}
}
