/*
 * Copyright 2007 Kickmogu Co. Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */



/*
 * 作成日: 2005/11/24
 *
 * TODO この生成されたファイルのテンプレートを変更するには次へジャンプ:
 * ウィンドウ - 設定 - Java - コード・スタイル - コード・テンプレート
 */
package com.kickmogu.rhythm.core;

import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Category;
import com.kickmogu.s2.DAOSequence;

public class RhythmTree {
	public final static String UNIQ_KEYNAME = "rhtym RhythmTree id";
	static Category log = Category.getInstance(RhythmTree.class.getName());

	private int id = -1;
	private String name;
	private RhythmTree parent = null;
	private List<RhythmTree> children = new ArrayList<RhythmTree>();

	/**
	 * Treeから条件のIDを持つインスタンスを探す
	 * @param condId
	 * @return
	 */
	public RhythmTree search(int condId) {
		if (getId() == condId) {
			return this;
		}
		for (int i = 0; i < children.size(); i++) {
			RhythmTree result = children.get(i).search(condId);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

	public boolean equals(Object tree) {
		if (! (tree instanceof RhythmTree)) {
			return false;
		}
		return id == ((RhythmTree) tree).id;
	}
	
	public void addToParent(RhythmTree parent) {
		setId(DAOSequence.getNextId(RhythmTree.UNIQ_KEYNAME));
		this.parent = parent;
		this.parent.children.add(this);
	}
	
	public void addToChild(RhythmTree child) {
		child.setId(DAOSequence.getNextId(RhythmTree.UNIQ_KEYNAME));
		child.setParent(this);
		children.add(child);
	}
	
	public void remove() {
		if (parent == null) {
			return;
		}
		parent.children.remove(this);
	}
	
	public void removeChild(RhythmTree child) {
		children.remove(child);
	}
	
	public void changeParent(RhythmTree newRoot) {
		if (parent != null) {
			parent.removeChild(this);
		}
		addToParent(newRoot);
	}

	/**
	 * 兄弟間の順序を変更する
	 * @param newSeq
	 */
	public void moveSeq(int newSeq) {
		if (parent == null) {
			return;
		}
		remove();
		parent.children.add(newSeq, this);
	}

	protected String getXmlOpenTag() {
		return "<" + this.getClass().getName().replace(".", "_")
			+ " id=\"" + getId() + "\""
			+ " name=\"" + getName() + "\">\n";
	}
	
	protected String getXmlCloseTag() {
		return "</" + this.getClass().getName().replace(".", "_") + ">\n";
	}
	
	/**
	 * @return XML表記の返却
	 */
	public String toXmlAll() {
		StringBuffer out = new StringBuffer();
		int level = getLevel();
		out.append(StringUtils.repeat("  ", level - 1));
		out.append(getXmlOpenTag());
		
		for (int i = 0; i < children.size(); i++) {
			out.append(children.get(i).toXmlAll());
		}
		out.append(StringUtils.repeat("  ", level - 1) + getXmlCloseTag());
		return out.toString();
	}
	
	/**
	 * @return ツリー構造のデバッグ表示
	 */
	public String toString() {
		StringBuffer out = new StringBuffer();
		int level = getLevel();
		out.append(StringUtils.repeat("\t", level - 1));
		out.append(getName() + "\n");
		
		for (int i = 0; i < children.size(); i++) {
			out.append(children.get(i).toString());
		}
		return out.toString();
	}
	
	public List<RhythmTree> getAll() {
		List<RhythmTree> results = new ArrayList<RhythmTree>();
		results.add(this);
		for (int i = 0; i < children.size(); i++) {
			results.addAll(children.get(i).getAll());
		}
		return results;
	}
	
	/*
	 * レベルを返す（最上位の親がレベル１、以下子供になるごとにレベルが
	 * １下がる）
	 */
	public int getLevel() {
		return parent == null ? 1 : parent.getLevel() + 1;
	}
	
	/**
	 * @return children を戻します。
	 */
	public List<RhythmTree> getChildren() {
		return children;
	}
	/**
	 * @param children children を設定。
	 */
	public void setChildren(List<RhythmTree> children) {
		this.children = children;
	}
	/**
	 * @return id を戻します。
	 */
	public int getId() {
		return id;
	}
	/**
	 * @param id id を設定。
	 */
	public void setId(int id) {
		this.id = id;
	}
	/**
	 * @return name を戻します。
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name name を設定。
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return parent を戻します。
	 */
	public RhythmTree getParent() {
		return parent;
	}
	/**
	 * @param parent parent を設定。
	 */
	public void setParent(RhythmTree parent) {
		this.parent = parent;
	}
}
