/**
 * Moxkiriya standalone Wiki.
 * Table row 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 com.wiki.standalone.moxkiriya.WikiEngine;

public class WikiTableRowBlockParser extends WikiBlockParserBase {
	/** startタグ(th)　*/
	private static final String START_TH_TAG = "<th";

	/** endタグ(th) */
	private static final String END_TH_TAG = "</th>\n";

	/** startタグ(td)　*/
	private static final String START_TD_TAG = "<td";

	/** endタグ(td) */
	private static final String END_TD_TAG = "</td>\n";

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

	/** WIKI記法の正規表現文字列 */
	public static final String NOTATION_REGEX = NOTATION_REGEX_LINEHEAD + ".*";

	/**
	 * 開始タグと終了タグのペア
	 */
	static class TagPair {
		/** 開始タグ */
		String startTag_;
		
		/** 終了タグ */
		String endTag_;

		/**
		 * コンストラクタ
		 * @param startTag
		 * @param endTag
		 */
		TagPair(String startTag, String endTag) {
			startTag_ = startTag;
			endTag_   = endTag;
		}
	}

	/** 開始文字と開始/終了タグのマップ */
	private static final LinkedHashMap<String, TagPair> tagPairHashMap_ = new LinkedHashMap<String, TagPair>() {
		private static final long serialVersionUID = 1L;
		{ put("!", new TagPair(START_TH_TAG, END_TH_TAG)); }
		{ put("|", new TagPair(START_TD_TAG, END_TD_TAG)); }
	};

	/** 開始/終了タグのペア */
	private TagPair  tagpair_;

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

	/** Daughterブロックパーサクリエイター */
	private WikiBlockParserCreator creator_;

	private StringBuffer rowBuf_;
	/**
	 * コンストラクタ
	 * @param wikiRepository
	 */
	public WikiTableRowBlockParser(WikiEngine wikiEngine) {
		this(wikiEngine, Status.INIT);
	}

	/**
	 * コンストラクタ
	 * @param wikiRepository
	 * @param status
	 */
	public WikiTableRowBlockParser(WikiEngine wikiEngine, Status status) {
		super(wikiEngine);
		status_  = status;
		creator_ = new WikiBlockParserCreator(wikiEngine);
		rowBuf_  = new StringBuffer("");
	}
	
	@Override
	public String startElementProcess(String line, StringBuffer buf) {
		status_ = Status.OPEN;

		String trimedLine  = line.trim();
		String firstLetter = trimedLine.substring(0, 1);
		
		tagpair_           = tagPairHashMap_.get(firstLetter);
		buf.append(tagpair_.startTag_ + " ");
		trimedLine         = trimedLine.substring(1);

		StringBuffer cellBuf       = new StringBuffer("");
		boolean      selectorFound = false;
		int          count;
		for(count = 0; count < trimedLine.length(); count++) {
			char letter = trimedLine.charAt(count);

			if(letter == '|') {
				break;
			}

			cellBuf.append(letter);

			if(selectorFound != true) {
				for(String key: selectorMap_.keySet()) {
					if(cellBuf.toString().equals(key) == true) {
						selectorFound = true;
						buf.append(key);
						break;
					}
				}
			}
			else {
				buf.append(letter);
			}
		}
		
		buf.append(">\n");

		if(selectorFound == true) {
			trimedLine = trimedLine.substring(count + 1);			
		}

		return trimedLine;
	}

	@Override
	public String parse(String line, StringBuffer buf) throws Exception {
		if( (line.startsWith("|") == true)
		 || (line.startsWith("!") == true)) {
			isBlockEnd_ = true;
			remain_     = line;
			line        = "";
		}
		else {
			if(status_ != Status.NESTING) {
				startDaughterParse(creator_, line);
				line = daughterParser_.startElementProcess(line, rowBuf_);
			}
			
			line = daughterParser_.parse(line, rowBuf_);
			if(daughterParser_.isBlockEnd() == true) {
				line = daughterParser_.endElementProcess(line, rowBuf_);
				status_ = Status.OPEN;
			}
		}

		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(tagpair_.endTag_);
		return remain_;
	}

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