package com.wiki.standalone.moxkiriya.parser.blockparser;

import com.wiki.standalone.moxkiriya.WikiEngine;

/**
 * 
 *
 */
public class WikiCodeBlockParser extends WikiBlockParserBase {
	/** WIKI記法の正規表現文字列　行頭パターン */
	public static final String NOTATION_REGEX_LINEHEAD = "<code[ \t]*>" + (".*");

	/** WIKI記法の正規表現文字列　行末パターン */
	public static final String NOTATION_REGEX_LINETAIL = "<*/[ \t]*code>" + ".*";
	
	/** WIKI記法の正規表現文字列 */
	public static final String NOTATION_REGEX = ".*" + NOTATION_REGEX_LINEHEAD
			+ ".*";

	/** 
	 *　 コンストラクタ
	 * @param file
	 */
	public WikiCodeBlockParser(WikiEngine wikiEngine) {
		this(wikiEngine, null, Status.INIT);
	}

	/**
	 * ネスト要素処理用コンストラクタ
	 * @param motherParser ネスト元要素parser
	 * @param file
	 * @param status
	 */
	public WikiCodeBlockParser(WikiEngine wikiEngine, WikiBlockParser motherParser, Status status) {
		super(wikiEngine);
		motherParser_  = motherParser;
		status_        = status;
		initialStatus_ = status;
	}
	
	@Override
	public String startElementProcess(String line, StringBuffer buf) {
		char[] charLine = line.toCharArray();
		String previous = "";
		String main     = "";

		for(count_ = 0; count_ < charLine.length; count_++) {
			if(charLine[count_] == '<') {
				String now     = line.substring(count_);

				if(now.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
					previous = line.substring(0, line.indexOf(now));
					main     = now;
					break;
				}
			}
		}
		
		if(previous.isEmpty() != true) {
			buf.append(inlineParse(previous));
		}
		
		return main;
	}

	@Override
	public String parse(String line, StringBuffer buf) throws Exception {
		char[] charLine = line.toCharArray();

		for(count_ = 0; count_ < charLine.length; count_++) {
			if(status_ == Status.NESTING) {
				String nestpart = new String(line.substring(count_));
				daughterParser_.parse(nestpart, buf);
				count_ += daughterParser_.getCount();

				if(daughterParser_.isBlockEnd() == true) {
					daughterParser_.endElementProcess(null, buf);
					status_        = Status.OPEN;
					daughterParser_ = null;
				}
				continue;
			}

			if(charLine[count_] == '<') {
				String now      = line.substring(count_);
				String nowLower = now.toLowerCase();
				String tagpart  = now.substring(0, now.indexOf(">") + ">".length());

				if(nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
					count_ += tagpart.length() - 1;

					if(status_ != Status.INIT) {
						tagpart = tagpart.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
					}
					startDaughterParse(new WikiBlockParserCreator.Creator() {
						@Override
						public WikiCodeBlockParser create(WikiEngine wikiEngine) {
							return new WikiCodeBlockParser(wikiEngine, WikiCodeBlockParser.this, Status.OPEN);
						}
					});
					buf.append(tagpart);
				}
				else if(nowLower.matches(NOTATION_REGEX_LINETAIL)) {
					if(status_ == Status.NESTING) {
						daughterParser_.parse(now, buf);
						count_ += daughterParser_.getCount() - 1;

						if(daughterParser_.isBlockEnd() == true) {
							status_        = Status.OPEN;
							daughterParser_ = null;
						}
					}
					else {
						remain_  = now.substring(now.indexOf(">") + ">".length());
						count_  += tagpart.length() - 1;

						if(initialStatus_ == Status.OPEN) {
							/*
							 * nest要素のparserとしてインスタンス生成された場合、 
							 */
							motherParser_.daughterElementCloseHelper(tagpart);
						}
						buf.append(tagpart);
						isBlockEnd_ = true;
						break;
					}
				}
				else {
					count_  += tagpart.length() - 1;
					buf.append(tagpart.replaceAll("<", "&lt;").replaceAll(">", "&gt;"));
				}
			}
			else if(status_ == Status.OPEN) {
				buf.append(charLine[count_]);				
			}
		}
		
		if(initialStatus_ == Status.INIT) {
			buf.append("\n");
		}

		return "";
	}

	@Override
	public String endElementProcess(String line, StringBuffer buf) {
		return remain_;
	}

	@Override
	public boolean isBlockEnd() {
		return isBlockEnd_;
	}
	
	@Override
	public String daughterElementCloseHelper(String tagPart) {
		return tagPart.replaceAll("<", "&lt;").replaceAll(">", "&gt;");
	}
}