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

import com.wiki.standalone.moxkiriya.WikiEngine;

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

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

	/** 
	 *　 コンストラクタ
	 */
	public WikiPreBlockParser(WikiEngine wikiEngine) {
		this(wikiEngine, Status.INIT);
	}

	/** 
	 *　 コンストラクタ
	 */
	public WikiPreBlockParser(WikiEngine wikiEngine, Status status) {
		super(wikiEngine);
		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(WikiPreBlockParser.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(WikiPreBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
					/*
					 * <pre>要素がネストしている場合
					 */
					count_ += tagpart.length() - 1;

					startDaughterParse(new WikiBlockParserCreator.Creator() {
						@Override
						public WikiPreBlockParser create(WikiEngine wikiEngine) {
							return new WikiPreBlockParser(wikiEngine, Status.OPEN);
						}
					});
					buf.append(tagpart);
				}
				else if(nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINEHEAD) == true) {
					/*
					 * <code>要素がネストしている場合
					 */
					count_ += tagpart.length() - 1;

					startDaughterParse(new WikiBlockParserCreator.Creator() {
						@Override
						public WikiCodeBlockParser create(WikiEngine wikiEngine) {
							return new WikiCodeBlockParser(wikiEngine, WikiPreBlockParser.this, Status.OPEN);
						}
					});
					buf.append(tagpart);
				}
				else if((nowLower.matches(WikiPreBlockParser.NOTATION_REGEX_LINETAIL) == true)
					|| (nowLower.matches(WikiCodeBlockParser.NOTATION_REGEX_LINETAIL) == true)) {
					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;
						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 (motherParser_ != null)
				? motherParser_.daughterElementCloseHelper(tagPart)
				: tagPart;
	}
}
