/*******************************************************************************
 * Copyright (c) 2003, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.intro.impl.presentations;

import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.ui.internal.intro.impl.model.AbstractIntroPage;
import org.eclipse.ui.internal.intro.impl.model.IntroModelRoot;
import org.eclipse.ui.internal.intro.impl.model.url.IntroURL;
import org.eclipse.ui.internal.intro.impl.model.url.IntroURLParser;

/**
 * A Location Listener that knows how to intercept OOBE action URLs. It also
 * knows how to update UI navigation hisutory.
 */
public class BrowserIntroPartLocationListener implements LocationListener {

    private BrowserIntroPartImplementation implementation;

    /**
     * Takes the implementation as an input.
     */
    public BrowserIntroPartLocationListener(
            BrowserIntroPartImplementation implementation) {
        this.implementation = implementation;
    }

    @Override
	public void changed(LocationEvent event) {
        String url = event.location;
        if (url == null)
            return;

        // guard against unnecessary History updates.
        Browser browser = (Browser) event.getSource();
        if (browser.getData("navigation") != null //$NON-NLS-1$
                && browser.getData("navigation").equals("true")) //$NON-NLS-1$ //$NON-NLS-2$
            return;

        IntroModelRoot model = implementation.getModel();
        IntroURLParser parser = new IntroURLParser(url);
        if (!parser.hasProtocol() || parser.getHost() == null
                || parser.getHost().equals("")) //$NON-NLS-1$
            // This will filter out two navigation events fired by the browser
            // on a setText. (about:blank and
            // res://C:\WINDOWS\System32\shdoclc.dll/navcancl.htm on windows,
            // and file:/// on Linux)
            return;

        if (model.isDynamic()) {
            // Update the history even with real URLs. Note that if we have
            // multiple embedded URL navigations due to frames, the
            // frameNavigation flag filters them. This flag is set here, and is
            // cleared by a progress listener, when all the frame navigation is
            // completed. We need to update history only in dynamic case. In
            // static case, the browser keeps the history.
            if (browser.getData("frameNavigation") != null) { //$NON-NLS-1$
                // this is at least the second frame navigation, remove last
                // history since it was added just as a filler.
                if (event.top == false && browser.getData("tempUrl") != null //$NON-NLS-1$
                        && browser.getData("tempUrl").equals("true")) { //$NON-NLS-1$ //$NON-NLS-2$
                    implementation.getHistory().removeLastHistory();
                    flagRemovedTempUrl();
                }
            }

            if (event.top == true) {
                // we are navigating to a regular fully qualified URL. Event.top
                // is true.
                flagStartOfFrameNavigation();
                implementation.updateHistory(url);
            }

            if (browser.getData("frameNavigation") == null //$NON-NLS-1$
                    && event.top == false) {
                // a new url navigation that is not in a top frame. It can
                // be a navigation url due to frames, it can be due to a true
                // single Frame navigation (when you click on a link inside a
                // Frame) or it is an embedded Help System topic navigation.
                AbstractIntroPage currentPage = model.getCurrentPage();
                if (currentPage.isIFramePage()) {
                    // it is an embedded Help System topic navigation. we are
                    // navigating to an injected iframe since event.top is
                    // false. Set the iframe url of the current iframe page, and
                    // add it
                    // to history.
                    currentPage.setIFrameURL(url);
                    implementation.updateHistory(currentPage);
                } else {
                    flagStartOfFrameNavigation();
                    flagStoredTempUrl();
                    implementation.updateHistory(url);
                }
            }

        }
        return;
    }

    /**
     * Intercept any LocationEvents on the browser. If the event location is a
     * valid IntroURL, cancel the event and execute the intro action that is
     * embedded in the URL
     */
    @Override
	public void changing(LocationEvent event) {
        String url = event.location;
        if (url == null)
            return;

        IntroModelRoot model = implementation.getModel();
        IntroURLParser parser = new IntroURLParser(url);
        if (parser.hasIntroUrl()) {
            // stop URL first.
            event.doit = false;
            // execute the action embedded in the IntroURL
            IntroURL introURL = parser.getIntroURL();
            introURL.execute();

            // In the case of dynamic Intro, guard against extra Frame
            // navigations. This can happen in the case of intro injected
            // IFrames or Frames included through intro xml content.
            // INTRO: user defined iframes in Intro pages are not properly
            // supported here, only Help system injected iframes.
            if (model.isDynamic()) {
                if ((introURL.getParameter(IntroURL.KEY_EMBED_TARGET) != null)
                        && introURL.getAction().equals(IntroURL.SHOW_PAGE))
                    flagStartOfNavigation();
            }
            return;
        }


    }




    public void flagStartOfFrameNavigation() {
        if (implementation.getBrowser().getData("frameNavigation") == null) //$NON-NLS-1$
            implementation.getBrowser().setData("frameNavigation", "true"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    public void flagEndOfFrameNavigation() {
        implementation.getBrowser().setData("frameNavigation", null); //$NON-NLS-1$
    }


    public void flagStartOfNavigation() {
        if (implementation.getBrowser().getData("navigation") == null) //$NON-NLS-1$
            implementation.getBrowser().setData("navigation", "true"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    public void flagEndOfNavigation() {
        implementation.getBrowser().setData("navigation", null); //$NON-NLS-1$
    }


    public void flagStoredTempUrl() {
        if (implementation.getBrowser().getData("tempUrl") == null) //$NON-NLS-1$
            implementation.getBrowser().setData("tempUrl", "true"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    public void flagRemovedTempUrl() {
        implementation.getBrowser().setData("tempUrl", null); //$NON-NLS-1$
    }


}
