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

import java.util.ArrayList;

import com.wiki.standalone.moxkiriya.WikiEngine;

/**
 * WikiInlineParserインスタンスを生成する。
 * @author Ryuhei Terada
 *
 */
public class WikiInlineParserCreator {
	/** WikiInlineParser Creator Table */
	private ArrayList<Creator> creatorList_;

	/** Wiki Eepository */
	private WikiEngine wikiEngine_;

	/** 
	 * CreatorテーブルのノードInterface
	 */
	public interface Creator {
		/**
		 * Wiki記法とパターンマッチングする。
		 * @param line
		 * @return マッチング結果
		 */
		public boolean matches(String line);
		
		/**
		 * InlineParser生成処理
		 * @param wikiRepository
		 * @return InlineParser
		 */
		public WikiInlineParser create(WikiEngine wikiEngine);
	};

	/** default WikiInlineParser Creator Table　*/
	private final static ArrayList<Creator> defaultCreatorList_ = new ArrayList<Creator>() {
		private static final long serialVersionUID = 1L;
		{
			/* WikiInternalLinkInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiInternalLinkInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiInternalLinkInlineParser(wikiEngine);
				}
			} );

			/* WikiExternalLinkInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiExternalLinkInlineParser.matches(line);
				}

				@Override
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiExternalLinkInlineParser(wikiEngine);
				}
			} );

			/* WikiBoldInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiBoldInlineParser.matches(line.toLowerCase());
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiBoldInlineParser(wikiEngine);
				}
			} );

			/* WikiItalicInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiItalicInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiItalicInlineParser(wikiEngine);
				}
			} );

			/* WikiUnderlineInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiUnderlineInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiUnderlineInlineParser(wikiEngine);
				}
			} );

			/* WikiLineThroughInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiLineThroughInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiLineThroughInlineParser(wikiEngine);
				}
			} );

			/* WikiUnorderedListItemInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiUnorderedListItemInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiUnorderedListItemInlineParser(wikiEngine);
				}
			} );
			/* WikiOrderedListItemInlineParser creator. */
			add(new Creator() {
				@Override
				public boolean matches(String line) {
					return WikiOrderedListItemInlineParser.matches(line);
				}

				@Override 
				public WikiInlineParser create(WikiEngine wikiEngine) {
					return new WikiOrderedListItemInlineParser(wikiEngine);
				}
			} );
		}
	};

	/**
	 * コンストラクタ
	 */
	public WikiInlineParserCreator(WikiEngine wikiEngine) {
		this(defaultCreatorList_, wikiEngine);
	}

	/**
	 * コンストラクタ
	 * @param creatorList
	 */
	public WikiInlineParserCreator(ArrayList<Creator> creatorList, WikiEngine wikiEngine) {
		creatorList_    = creatorList;
		wikiEngine_ = wikiEngine;
	}
	
	/**
	 * lineのSyntaxにマッチするWikiInlineParserのインスタンスを生成する。
	 * @param line
	 * @param file
	 * @return WikiInlineParser
	 */
	public WikiInlineParser create(String line) {
		WikiInlineParser parser      = null;
		StringBuffer     withoutElem = new StringBuffer("");

		if( (line.isEmpty() != true)
		 && (line.contains("<") == true)
		 && (line.contains(">") == true)) {
			withoutElem.append(line.substring(0, line.indexOf("<")));
			withoutElem.append(line.substring(line.lastIndexOf(">") + ">".length()));
		}
		else {
			withoutElem.append(line);
		}

		if(withoutElem.toString().isEmpty() != true) {
			for(Creator creator: creatorList_) {
				if(creator.matches(withoutElem.toString()) == true) {
					parser = creator.create(wikiEngine_);
					break;
				}
			}		
		}
		
		if(parser == null) {
			parser = new WikiDefaultInlineParser(wikiEngine_);
		}
		
		return parser;
	}
}
