package org.limewire.ui.swing.browser;

import java.net.URI;
import java.net.URISyntaxException;

import org.limewire.concurrent.ManagedThread;
import org.limewire.core.api.magnet.MagnetFactory;
import org.limewire.core.api.magnet.MagnetLink;
import org.limewire.ui.swing.util.MagnetHandler;
import org.limewire.ui.swing.util.NativeLaunchUtils;
import org.limewire.util.URIUtils;
import org.mozilla.browser.XPCOMUtils;
import org.mozilla.interfaces.nsIDOMEventTarget;
import org.mozilla.interfaces.nsIDOMWindow2;
import org.mozilla.interfaces.nsIWebBrowserChrome;
import org.w3c.dom.Node;

import com.google.inject.Inject;
import com.google.inject.Provider;

public class BrowserUtils {

    private static final LimeDomListener DOM_ADAPTER = new LimeDomListener();

    /**
     * Registers a handler for URLs with target = "_blank"
     */
    @Inject
    public static void registerBlankTarget() {
        addTargetedUrlAction("_blank", new UriAction() {
            @Override
            public boolean uriClicked(final TargetedUri targetedUrl) {
                // Open url in new thread to keep Mozilla thread responsive
                new ManagedThread(new Runnable() {
                    @Override
					public void run() {
                        NativeLaunchUtils.openURL(targetedUrl.getUri());
                    }
                }).start();
                return true;
            }
        });
    }

    @Inject
    public static void registerMagnetProtocol(final MagnetFactory magnetFactory,
            final Provider<MagnetHandler> magnetHandler) {
        addProcotolHandlerAction("magnet", new UriAction() {
            @Override
            public boolean uriClicked(TargetedUri targetedUrl) {
                try {
                    URI uri = URIUtils.toURI(targetedUrl.getUri());
                    MagnetLink[] magnetLinks = magnetFactory.parseMagnetLink(uri);
                    for (MagnetLink magnetLink : magnetLinks) {
                        magnetHandler.get().handleMagnet(magnetLink);
                    }
                } catch (URISyntaxException e) {
                    return false;
                }
                return true;
            }
        });
    }
    
    @Inject
    public static void registerMailToProtocol(final MagnetFactory magnetFactory) {
        addProcotolHandlerAction("mailto", new UriAction() {
            @Override
            public boolean uriClicked(final TargetedUri targetedUrl) {
             // Open url in new thread to keep Mozilla thread responsive
                new ManagedThread(new Runnable() {
                    @Override
					public void run() {
                        NativeLaunchUtils.openURL(targetedUrl.getUri());
                    }
                }).start();
                return true;
            }
        });
    }

    /**
     * Adds a {@link UriAction} for the specified target. They are only invoked
     * if there is no matching protocol action.
     */
    public static void addTargetedUrlAction(String target, UriAction action) {
        DOM_ADAPTER.addTargetedUrlAction(target, action);
    }

    /**
     * Adds a {@link UriAction} for the specified URI protocol (magnet, etc..)
     */
    public static void addProcotolHandlerAction(String protocol, UriAction action) {
        DOM_ADAPTER.addProtocolHandlerAction(protocol, action);
    }

    /**
     * 
     * @return true if node is a text input, password input or textarea
     */
    static boolean isTextControl(Node node) {

        boolean isText = false;

        if ("input".equalsIgnoreCase(node.getNodeName())) {
            Node type = node.getAttributes().getNamedItem("type");
            // null, text or password are text controls. Filters out checkbox,
            // etc
            isText = type == null || "text".equalsIgnoreCase(type.getNodeValue())
                    || "password".equalsIgnoreCase(type.getNodeValue()) || "search".equalsIgnoreCase(type.getNodeValue());
        } else {
            isText = "textarea".equalsIgnoreCase(node.getNodeName());
        }

        return isText;
    }

    /**
     * Adds LimeDomListener to chromeAdapter.
     */
    static void addDomListener(final nsIWebBrowserChrome chrome) {
        nsIDOMEventTarget eventTarget = XPCOMUtils.qi(chrome.getWebBrowser().getContentDOMWindow(),
                nsIDOMWindow2.class).getWindowRoot();
        // TODO: some way to listen for javascript?
        eventTarget.addEventListener("click", DOM_ADAPTER, true);
        eventTarget.addEventListener("submit", DOM_ADAPTER, true);
    }

    static void removeDomListener(final nsIWebBrowserChrome chrome) {
        nsIDOMEventTarget eventTarget = XPCOMUtils.qi(chrome.getWebBrowser().getContentDOMWindow(),
                nsIDOMWindow2.class).getWindowRoot();
        eventTarget.removeEventListener("click", DOM_ADAPTER, true);
        eventTarget.removeEventListener("submit", DOM_ADAPTER, true);
    }

}
