package org.phosphoresce.commons.html.util;

import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;

import org.phosphoresce.commons.html.HTMLCommentElement;
import org.phosphoresce.commons.html.HTMLDocumentElement;
import org.phosphoresce.commons.html.HTMLElement;
import org.phosphoresce.commons.html.HTMLTagElement;
import org.phosphoresce.commons.html.HTMLTextElement;

/**
 * HTMLドキュメントパースコールバッククラス<br>
 *
 * @author Kitagawa<br>
 *
 *<!--
 * 更新日		更新者			更新内容
 * 2008/11/19	Kitagawa		新規作成
 *-->
 */
public class HTMLDocumentParserCallbak extends ParserCallback {

	/** HTMLドキュメントエレメント */
	private HTMLDocumentElement document;

	/** パースカレントエレメント */
	private HTMLElement current;

	/**
	 * コンストラクタ<br>
	 */
	public HTMLDocumentParserCallbak() {
		super();
		this.document = new HTMLDocumentElement();
		this.current = this.document;
	}

	/**
	 * HTMLドキュメントエレメントを取得します。<br>
	 * @return HTMLドキュメントエレメント
	 */
	public HTMLDocumentElement getDocument() {
		return document;
	}

	/**
	 * 単一タグで完了するタグ(<tagname>/<tagname/>)をハンドルした際の処理を実行します。<br>
	 * @param tag タグオブジェクト
	 * @param attribute 属性オブジェクト
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit$ParserCallback#handleSimpleTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
	 */
	public void handleSimpleTag(Tag tag, MutableAttributeSet attribute, int pos) {
		// カレントに子エレメントを追加
		HTMLTagElement newElement = new HTMLTagElement(tag, attribute.copyAttributes());
		current.addChild(newElement);

		super.handleSimpleTag(tag, attribute, pos);
	}

	/**
	 * 開始タグをハンドルした際の処理を実行します。<br>
	 * @param tag タグオブジェクト
	 * @param attribute 属性オブジェクト
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit$ParserCallback#handleStartTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
	 */
	public void handleStartTag(Tag tag, MutableAttributeSet attribute, int pos) {
		// カレントに子エレメントを追加し、カレントを置換
		HTMLTagElement newElement = new HTMLTagElement(tag, attribute.copyAttributes());
		current.addChild(newElement);
		current = newElement;

		super.handleStartTag(tag, attribute, pos);
	}

	/**
	 * 終了タグをハンドルした際の処理を実行します。<br>
	 * @param tag タグオブジェクト
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleEndTag(javax.swing.text.html.HTML.Tag, int)
	 */
	public void handleEndTag(Tag tag, int pos) {
		// カレントエレメントをその親エレメントに置換
		if (current.isRoot()) {
			//Logger.getLogger(getClass().getName()).log(Level.WARNING, "Lucked start tag  [" + tag + "]");
		} else if (!(current instanceof HTMLTagElement)) {
			//Logger.getLogger(getClass().getName()).log(Level.WARNING, "Current is no tag element [" + current + "]");
		} else if (!((HTMLTagElement) current).getName().equals(tag.toString())) {
			//Logger.getLogger(getClass().getName()).log(Level.WARNING, "Current tag is not equal [" + tag + "]");
		} else {
			current = current.getParent();
		}

		super.handleEndTag(tag, pos);
	}

	/**
	 * コメントをハンドルした際の処理を実行します。<br>
	 * @param data コメントデータ
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleComment(char[], int)
	 */
	public void handleComment(char[] data, int pos) {
		// カレントエレメントにコメントを追加
		HTMLCommentElement newElement = new HTMLCommentElement(new String(data));
		current.addChild(newElement);

		super.handleComment(data, pos);
	}

	/**
	 * ストリームの解析が終了し、flushが実行される直前の処理を実行します。<br>
	 * @param eol 行の最終文字列
	 * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleEndOfLineString(java.lang.String)
	 */
	public void handleEndOfLineString(String eol) {
		// HTMLドキュメントで完結していることをチェック
		if (!current.equals(document)) {
			//Logger.getLogger(getClass().getName()).log(Level.WARNING, "HTML Document Element Closing Parse Error");
		}

		super.handleEndOfLineString(eol);
	}

	/**
	 * エラーをハンドルした際の処理を実行します。<br>
	 * @param message エラーメッセージ
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleError(java.lang.String, int)
	 */
	public void handleError(String message, int pos) {
		// パースエラーハンドリング
		//Logger.getLogger(getClass().getName()).log(Level.WARNING, "Parse Error : " + message);

		super.handleError(message, pos);
	}

	/**
	 * テキストをハンドルした際の処理を実行します。<br>
	 * @param data 文字配列
	 * @param pos ポジション
	 * @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleText(char[], int)
	 */
	public void handleText(char[] data, int pos) {
		// カレントエレメントにテキストを追加
		HTMLTextElement newElement = new HTMLTextElement(new String(data));
		current.addChild(newElement);

		super.handleText(data, pos);
	}
}

