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

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.wiki.standalone.moxkiriya.SettingManager;
import com.wiki.standalone.moxkiriya.WikiEngine;

public class WikiExternalLinkInlineParser extends WikiInlineParserBase {
	/** WIKI開始トークン */
	public static final String WIKI_TOKEN_START = "[";

	/** WIKI開始トークン */
	public static final String WIKI_TOKEN_END   = "]";

	/** WIKI記法の正規表現文字列　先頭頭パターン */
	public static final String PATTERN_START = Pattern.quote(WIKI_TOKEN_START)
												+ "[^"
												+ Pattern.quote("[")
												+ "]";

	/** WIKI記法の正規表現文字列　末尾パターン */
	public static final String PATTERN_END = "[^]]"
												+ Pattern.quote(WIKI_TOKEN_END);

	/** startタグ */
	private static final String START_TAG = "<a href=";

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

	/** icon startタグ*/
	private static final String START_ICON_TAG = "<img src=";

	/** icon endタグ */
	private static final String END_ICON_TAG = "</img>";

	/** external link icon画像名 */
	private static final String EXTERNAL_LINK_ICON = "icon\\Icon_External_Link.png";
	
	/** Link先のURL */
	private String url_;
	
	/** Link先のtextNode */
	private String textNode_;

	/**
	 * スキーマリスト
	 */
	private static final ArrayList<String> schemeList = new ArrayList<String>() {
		private static final long serialVersionUID = 1L;
		{ add("http://"); }
		{ add("https://"); }
		{ add("file://"); }
	};
	
	/**
	 * コンストラクタ
	 */
	public WikiExternalLinkInlineParser(WikiEngine wikiEngine) {
		super(wikiEngine);
	}

	/**
	 * lineとWiki記法をマッチングする
	 * @param line
	 * @return マッチング結果
	 */
	public static boolean matches(String line) {
		boolean isMatch = false;
		
		Matcher startMatcher
			= Pattern.compile(WikiExternalLinkInlineParser.PATTERN_START).matcher(line);

		if(startMatcher.find() == true) {
			/*
			 * PATTERN_STARTの開始位置を取得
			 */						
			int     startIndex = startMatcher.start();

			/*
			 * PATTERN_ENDの開始位置を取得
			 */
			String   startString = line.substring(startIndex + 1);
			Matcher  endMatcher  = Pattern.compile(WikiExternalLinkInlineParser.PATTERN_END).matcher(startString);
			
			if(endMatcher.find() == true) {
				isMatch = isSchemeString(startString);
			}
		}
		
		return isMatch;
	}

	@Override
	public String[] devideLine(String line) {
		int      depth         = 0;
		char[]   charArrayLine = line.toCharArray();
		int      startIndex    = -1;
		int      endIndex      = -1;
		int      lastIndex     = -1;
		boolean  withinElem    = false;
		
		for(int count = 0; count < charArrayLine.length; count++) {
			if(charArrayLine[count] == '>') {
				withinElem = false;
				continue;
			} else if(charArrayLine[count] == '<') {
				withinElem = true;
			}
			
			if(withinElem == true) {
				/*
				 * HTML要素内をスキップ
				 */
				continue;
			}
			
			if(charArrayLine[count] == '[') {
				String startString = line.substring(count + 1);
				if(isSchemeString(startString) == true) {
					if(startIndex != -1) {
						/*
						 * 次の外部リンクの開始の場合、
						 */
						endIndex = lastIndex;
						break;
					}
					else if(depth == 0) {
						startIndex = count;
					}
				}
				else if(startString.startsWith("[")) {
					/*
					 * 内部リンクの開始に到達した場合、
					 */
					endIndex = lastIndex;
					break;					
				}
				depth++;
			}
			else if(charArrayLine[count] == ']') {
				lastIndex = count;
				if(depth > 0) {
					depth--;
					
					if(depth == 0) {
						endIndex = count;
						break;
					}
				}
			}
		}

		if(endIndex == -1) {
			endIndex = (lastIndex == -1) ? line.length() - 1 : lastIndex;
		}

		String split0 = line.substring(0, startIndex);
		String split1 = line.substring(startIndex, endIndex + 1);
		String split2 = line.substring(endIndex + 1);

		return new String[] {split0, split1, split2};
	}	

	@Override
	public String deleteWikiToken(String line) {
        String deleteTop = line.replaceFirst(Pattern.quote(WIKI_TOKEN_START), "");
        String text      = deleteTop.substring(0, deleteTop.lastIndexOf(WIKI_TOKEN_END));

        if(text.contains("|") == true) {
                url_      = text.substring(0, text.indexOf("|"));
                textNode_ = text.substring(text.indexOf("|") + "|".length());
        }
        else {
                url_      = text;
                textNode_ = text;
        }
        return textNode_.replaceAll(Pattern.quote("["), "&#91;")
        		.replaceAll(Pattern.quote("]"), "&#93;");
	}

	@Override
	public void startElementProcess(StringBuffer buf) {
		buf.append(START_TAG);
		buf.append("\"");
		buf.append(url_);
		buf.append("\">");
	}

	@Override
	public void textNodeProcess(StringBuffer buf, String textNode) {
		buf.append(textNode);
	}
	
	@Override
	public String getStartPattern() {
		return PATTERN_START;
	}

	@Override
	public void endElementProcess(StringBuffer buf) {
		try {
			buf.append(START_ICON_TAG);
			
			SettingManager settingMgr = SettingManager.getInstance();
			String         Approot    = settingMgr.get(SettingManager.SETINGKEY_MOXKIRIYAROOT);
			String         iconPath   = Approot + "\\" + EXTERNAL_LINK_ICON;
			URL            url        = new File(iconPath).toURI().toURL();
			buf.append("\"" + url.toString() + "\">");
	
			buf.append(END_ICON_TAG);
			buf.append(END_TAG);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}

	@Override
	public String getEndPattern() {
		return PATTERN_END;
	}

	/**
	 * lineがscheme文字列で始まるか判定する。
	 * @param line
	 * @return 判定結果
	 */
	private static boolean isSchemeString(String line) {
		boolean result = false;

		for(String scheme: schemeList) {
			if(line.startsWith(scheme) == true) {
				result = true;
				break;
			}
		}
		
		return result;
	}
}
