package de.tbressler.waterrower.workout.ui.utils;

import de.tbressler.waterrower.workout.log.Log;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.scene.web.WebView;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.html.HTMLAnchorElement;

import java.awt.*;
import java.net.URI;

import static de.tbressler.waterrower.workout.log.Log.APPLICATION;
import static java.awt.Desktop.isDesktopSupported;
import static javafx.concurrent.Worker.State.SUCCEEDED;

/**
 * A hyperlink listener that prevents opening URLs in internal browser. Instead it uses the default
 * external browser.
 *
 * Taken from:
 * https://stackoverflow.com/questions/15555510/javafx-stop-opening-url-in-webview-open-in-browser-instead
 *
 * @author JAntares (https://stackoverflow.com/users/5508764/jantares)
 * @version 1.0
 */
public class HyperlinkRedirectListener implements ChangeListener<Worker.State>, EventListener {

    private static final String CLICK_EVENT = "click";
    private static final String ANCHOR_TAG = "a";

    private final WebView webView;

    public HyperlinkRedirectListener(WebView webView) {
        this.webView = webView;
    }

    @Override
    public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
        if (SUCCEEDED.equals(newValue)) {
            Document document = webView.getEngine().getDocument();
            NodeList anchors = document.getElementsByTagName(ANCHOR_TAG);
            for (int i = 0; i < anchors.getLength(); i++) {
                Node node = anchors.item(i);
                EventTarget eventTarget = (EventTarget) node;
                eventTarget.addEventListener(CLICK_EVENT, this, false);
            }
        }
    }

    @Override
    public void handleEvent(Event event) {
        HTMLAnchorElement anchorElement = (HTMLAnchorElement)event.getCurrentTarget();
        String href = anchorElement.getHref();

        if (isDesktopSupported()) {
            openLinkInSystemBrowser(href);
        } else {
            Log.warn(APPLICATION, "OS does not support desktop operations like browsing. Cannot open link '"+href+"'!");
        }

        event.preventDefault();
    }

    private void openLinkInSystemBrowser(String url) {
        try {
            URI uri = new URI(url);
            Desktop.getDesktop().browse(uri);
        } catch (Throwable e) {
            Log.error("Error on opening link '"+url+"' in system browser!", e);
        }
    }

}