package jp.sourceforge.asclipse.as3;

import java.util.List;

import jp.sourceforge.asclipse.as3.element.AS3Element;

import org.antlr.runtime.Token;
import org.antlr.runtime.tree.CommonTree;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * デバッグ用のユーティリティクラス。
 * @author shin1ogawa
 */
public class DebugUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(DebugUtil.class);


	private DebugUtil() {
	}

	/**
	 * {@link AS3Element}の構造をインデント付きで表示する。
	 * @param parent
	 * @param depth
	 */
	public static void debugAS3Element(AS3Element parent, int depth) {
		String indent = StringUtils.repeat("\t", depth);
		LOGGER.debug(String.format("[%5d,%3d]-[%5d,%3d]", parent.getStartLine(), parent
			.getCharPositionInLine(), parent.getEndLine(), parent.getEndCharPositionInLine())
				+ indent + parent.getTitle());
		if (parent.getChildCount() > 0) {
			List<AS3Element> children = parent.getChildren();
			for (AS3Element child : children) {
				debugAS3Element(child, depth + 1);
			}
		}
	}

	/**
	 * ツリー構造をインデント付きで表示する。
	 * @param tree
	 */
	public static void debug(CommonTree tree) {
		debugTree(tree, 0);
	}

	private static void debugTree(CommonTree tree, int depth) {
		String indent = StringUtils.repeat("  ", depth);
		int childCount = tree.getChildCount();
		if (childCount == 0) {
			debugToken(tree, indent);
			return;
		} else {
			debugToken(tree, indent);
		}
		for (int i = 0; i < childCount; i++) {
			CommonTree child = (CommonTree) tree.getChild(i);
			debugTree(child, depth + 1);
		}
	}

	private static void debugToken(CommonTree tree, String indent) {
		if (tree == null) {
			return;
		}
		Token token = tree.getToken();
		if (token == null) {
			return;
		}
		StringBuilder b = new StringBuilder();
		b.append("[").append(String.format("%5d", token.getLine())).append(",").append(
				String.format("%3d", token.getCharPositionInLine())).append("]");
		Position endPos = getEndPos(tree);
		b.append("-[").append(String.format("%5d", endPos.line)).append(",").append(
				String.format("%3d", endPos.charPositionInLine)).append("]");
		//b.append("type=").append(tree.getType()).append(":");
		b.append(indent).append(token.getText());
		LOGGER.debug(b.toString());
	}

	private static Position getEndPos(CommonTree tree) {
		if (tree.getChildCount() == 0) {
			Token token = tree.getToken();
			String text = token.getText();
			return new Position(token.getLine(), token.getCharPositionInLine()
					+ (text != null ? text.length() : 0));
		} else {
			int tokenStopIndex = tree.getTokenStopIndex();
			CommonTree child = (CommonTree) tree.getChild(tree.getChildCount() - 1);
			if (child == null) {
				System.out.println("start=" + tree.getTokenStartIndex() + ", " + "stop="
						+ tokenStopIndex + ", childCount=" + tree.getChildCount() + ", this="
						+ tree.toString());
			}
			return getEndPos(child);
		}
	}


	private static class Position {

		public final int line;

		public final int charPositionInLine;


		public Position(int line, int charPositionInLine) {
			super();
			this.line = line;
			this.charPositionInLine = charPositionInLine;
		}
	}
}
