/**
 * Moxkiriya standalone Wiki.
 * '<table>' Blocklevel element parser, processor.
 * 
 * @author Ryuhei Terada
 * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
 */
package com.wiki.standalone.moxkiriya.parser.blockparser;

import java.util.LinkedHashMap;
import java.util.regex.Pattern;

import com.wiki.standalone.moxkiriya.WikiEngine;

public class WikiTableBlockParser extends WikiBlockParserBase {
	/** startタグ　*/
	private static final String START_TAG = "<div><table";

	/** endタグ*/
	private static final String END_TAG = "</table></div>\n";

	/** WIKI記法の正規表現文字列　行頭パターン */
	private static final String NOTATION_REGEX_LINEHEAD = "^[ \t]*"
														+ Pattern.quote("{|");

	/** WIKI記法の正規表現文字列　行末パターン */
	private static final String NOTATION_REGEX_LINETAIL = "^[ \t]*"
														+ Pattern.quote("|}");
	
	/** WIKI記法の正規表現文字列 */
	public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD + ".*";

	/** CSSセレクターマップ */
	private static final LinkedHashMap<String, String> selectorMap_ = new LinkedHashMap<String, String>() {
		private static final long serialVersionUID = 1L;
		{ put("#", "id="); }
		{ put(".", "class=");}
	};

	/** table 1行分の文字列を蓄積するバッファ */
	private StringBuffer rowBuf_;
	
	/** Daughterブロックパーサクリエイター */
	private final WikiBlockParserCreator creator_ = new WikiBlockParserCreator(wikiEngine_) {
		@Override
		public WikiBlockParser create(String line) {
			return new WikiTableRowBlockParser(wikiEngine_);
		}
	};

	/**
	 * コンストラクタ
	 * @param wikiRepository
	 */
	public WikiTableBlockParser(WikiEngine wikiEngine) {
		super(wikiEngine);
		status_ = Status.INIT;
	}
	
	@Override
	public String startElementProcess(String line, StringBuffer buf) {
		buf.append(START_TAG);

		String style = line.replaceFirst(NOTATION_REGEX_LINEHEAD, "").trim();
		String selector = "";

		if(style.isEmpty() != true) {
			/*
			 * 表開始マークアップ後の文字列のスタイルシートのセレクタ形式か判定する
			 */
			for(String key: selectorMap_.keySet()) {
				if(style.startsWith(key) == true) {
					selector = selectorMap_.get(key);
					style    = style.substring(style.indexOf(key) + key.length());
					break;
				}
			}
	
			if(selector.isEmpty() != true) {
				buf.append(" ");
				buf.append(selector);
				buf.append("\"" + style + "\"");
			}
		}
		buf.append(">\n");

		return "";
	}

	@Override
	public String parse(String line, StringBuffer buf) throws Exception {
		if(line.matches(NOTATION_REGEX_LINETAIL+ ".*") == true) {
			isBlockEnd_ = true;
			remain_     = line.replaceFirst(NOTATION_REGEX_LINETAIL, "");
			line        = "";
		}
		else {
			if(rowBuf_ == null) {
				rowBuf_ = new StringBuffer();
			}
			
			if(status_ == Status.INIT) {
				status_ = Status.OPEN;
			}
			else if(status_ == Status.OPEN) {
				startDaughterParse(creator_, line);
				line = daughterParser_.startElementProcess(line, rowBuf_);					
			}
			else if(status_ == Status.NESTING) {
				line = daughterParser_.parse(line, rowBuf_);
				if(daughterParser_.isBlockEnd() == true) {
					line = daughterParser_.endElementProcess(line, rowBuf_);
					status_ = Status.OPEN;
				}					
			}
		}

		if(line.startsWith("|-") == true) {
			flushRowBuf(buf);
			line    = "";
		}
		return line;
	}

	@Override
	public String endElementProcess(String line, StringBuffer buf) {
		if(status_ == Status.NESTING) {
			daughterParser_.endElementProcess(line, rowBuf_);
			status_ = Status.OPEN;
		}
		flushRowBuf(buf);
		buf.append(END_TAG + "\n");
		return remain_;
	}

	/**
	 * 表の行終端や表終端マークアップに到達したときに1行分の文字列をbufに書き込む
	 * @param buf
	 */
	private void flushRowBuf(StringBuffer buf) {
		if( (rowBuf_ != null)
		 && (rowBuf_.length() > 0)) {
			buf.append("<tr>\n");
			buf.append(rowBuf_);
			buf.append("</tr>\n");
			rowBuf_ = null;
		}
	}
}
