/**
 * Moxkiriya standalone Wiki.
 * Wiki preview window controller.
 * 
 * @author Ryuhei Terada
 * See the '<a href="{@docRoot}/copyright.html">Copyright</a>'
 */
package com.wiki.standalone.moxkiriya;

import java.awt.Desktop;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MouseEvent;
import org.w3c.dom.html.HTMLAnchorElement;

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Hyperlink;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;

/**
 * Controll preview window.
 *
 */
public class WikiHelpWindowController implements Initializable {
	/** Wiki preview window */
	private WikiHelpWindow wikiHelpWindow_;

	@FXML private Button    buttonClose;
	@FXML private Hyperlink hyperlinkSidemenuHelpTOC;
	@FXML private WebView   webViewSidemenu;
	@FXML private WebView   webViewMain;

	/** Help Sidemenu Wiki engine */
//	private WikiEngine helpSidemenuWikiEngine_;

	/** Help Main Wiki engine */
	private WikiEngine helpMainWikiEngine_;

	/** Help page map. */
	private HashMap<String, PageData> pageMap_;

	/** Help TOC page title key */
	private static final String KEY_HELP_TOC_TITLE = "key.Help.TOC";

	/** Help TOC page title */
	private String HelpTOCTitle;

	/** Help TOC PageData */
	private PageData helpTOCPageData_ = null;
	
	@Override
	public void initialize(URL url, ResourceBundle resource) {
		try {
//			helpSidemenuWikiEngine_   = new WikiEngine();
			helpMainWikiEngine_       = new WikiEngine();

			HelpTOCTitle = resource.getString(KEY_HELP_TOC_TITLE);

			setLinkClickListner(webViewMain.getEngine());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * WikiPreviewWindow setter.
	 */
	public void setWikiHelpWindow(WikiHelpWindow helpWindow) {
		wikiHelpWindow_ = helpWindow;
	}

	/**
	 * Wiki repository setter.
	 * @param wikiRepository
	 */
	public void setWikiRepository(WikiRepository wikiRepository) {
//		helpSidemenuWikiEngine_.setWikiRepository(wikiRepository);
		helpMainWikiEngine_.setWikiRepository(wikiRepository);
	}

	@FXML
	public void onActionButtonClose(ActionEvent event) {
		((Node)event.getSource()).getScene().getWindow().hide();
	}

	@FXML
	public void onMouseClickedSidemenuHyperlinkHelpTOC() {
		try {
			loadTableOfContent();
		} catch (Exception e) {
			e.printStackTrace();
		}			
	}

	/**
	 * Table of Content loader.
	 * @throws Exception
	 */
	public void loadTableOfContent() throws Exception {
		if(helpTOCPageData_ == null) {
//			pageMap_     = helpSidemenuWikiEngine_.queryPageNamespace(WikiRepository.PROPERTY_HELP);
			pageMap_     = helpMainWikiEngine_.queryPageNamespace(WikiRepository.PROPERTY_HELP);
	
			for(PageData node: pageMap_.values()) {
				if(node.getTitle().equals(HelpTOCTitle) == true) {
					helpTOCPageData_ = node;
					break;
				}
			}
		}

		if (helpTOCPageData_ != null) {
//			String helpSidemenuContents = helpSidemenuWikiEngine_.parse(helpTOCPageData_);
//			webViewSidemenu.getEngine().loadContent(helpSidemenuContents);
			String content = helpMainWikiEngine_.parse(helpTOCPageData_);
			webViewMain.getEngine().loadContent(content);
		}
	}

	/**
	 * A要素のクリックリスナーを登録する。
	 * @param webEngine
	 */
	private void setLinkClickListner(WebEngine webEngine) {
		webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
			@Override
			public void changed(ObservableValue<? extends State> arg0, State oldState, State newState) {
				WebView        webView  = webViewMain;
				EventListener  listener = new EventListener() {						
					@Override
					public void handleEvent(org.w3c.dom.events.Event event) {
						try {
							MouseEvent        mouseEvent  = (MouseEvent)event;
							EventTarget       target      = mouseEvent.getCurrentTarget();

							if(isExternalLink(target) == true) {
								/*
								 * WebEngineのデフォルトの動作(リンク先ページをロード)をキャンセル
								 */
								event.preventDefault();
							}
							else {
								internalLinkHandle(target);
							}
						} catch (Exception e) {
							e.printStackTrace();
						}
					}

					/**
					 * targetが外部リンクか判定する。
					 * @param target
					 * @return
					 */
					private boolean isExternalLink(EventTarget target) {
						final ArrayList<String> schemeList = new ArrayList<String>() {
							private static final long serialVersionUID = 1L;
							{ add("http://"); }
							{ add("https://"); }
							{ add("file://"); }
						};

						HTMLAnchorElement aElem      = (HTMLAnchorElement)target;
						String            href       = aElem.getAttribute("href");
						boolean           isExternal = false;

						for(String scheme: schemeList) {
							if(href.startsWith(scheme) == true) {
								isExternal = true;
								break;
							}
						}

						return isExternal;
					}
					
					/**
					 * InternalLinkを処理する。
					 * @param target
					 * @throws Exception
					 */
					private void internalLinkHandle(EventTarget target) throws Exception {
						HashMap<String, PageData> pageDataMap;
						HTMLAnchorElement         anchor    = (HTMLAnchorElement)target;
						String                    href      = anchor.getAttribute("href");
						String                    pageTitle = URLDecoder.decode(href, "UTF-8");
						String                    uuid      = anchor.getAttribute(WikiEngine.ATTRIBUTE_JCR_UUID);

						if(uuid != null) {
							pageDataMap = helpMainWikiEngine_.queryPageUUID(uuid);
						}
						else {
							pageDataMap = helpMainWikiEngine_.queryPageTitle(pageTitle);								
						}
						if(pageDataMap.size() == 1) {
							PageData pageData = pageDataMap.values().iterator().next();
							if(pageData.getNamespace().equals(WikiRepository.PROPERTY_HELP) == true) {
								String content = helpMainWikiEngine_.parse(pageData);
								webViewMain.getEngine().loadContent(content);
							}
						}
					}
            	};

				if(newState == State.SUCCEEDED) {
					Document  doc   = webView.getEngine().getDocument();
		            NodeList  listA = doc.getElementsByTagName("a");
		            
		            for(int index = 0; index < listA.getLength(); index++) {
		            	((EventTarget)listA.item(index)).addEventListener("click", listener, false);
		            }
				}
			}
		});
	}
}
