/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.intro.impl.model;

import java.net.*;
import java.util.*;

import org.eclipse.core.runtime.*;
import org.eclipse.jface.util.*;
import org.eclipse.ui.*;
import org.eclipse.ui.internal.intro.impl.model.loader.*;
import org.eclipse.ui.internal.intro.impl.util.*;
import org.osgi.framework.*;
import org.w3c.dom.*;

/**
 * The root class for the OOBE model. It loads the configuration into the
 * appropriate classes.
 * 
 * Model rules:
 * <ul>
 * <li>if an attribute is not included in the markup, its value will be null in
 * the model.</li>
 * <li>the current page id is set silently when loading the model. You do not
 * need the event notification on model load.</li>
 * <li>Children of a given parent (ie: model root, page, or group) *must* have
 * distinctive IDs otherwise resolving includes and extensions may fail.</li>
 * <li>Containers have the concept of loading children and resolving children.
 * At the model root level, resolving children means resolving ALL extensions of
 * model. At the container level, resolving children means resolving includes.
 * </li>
 * <li>Extensions are resolved before includes at the container level to avoid
 * race conditions. eg: if a page includes a shared group and an extension
 * extends this shared group, you want the include to get the extended group and
 * not the original group.</li>
 * <li>Resolving extensions should not resolve includes. No need to load other
 * models when we dont have to. Plus, extensions can only reference anchors, and
 * so no need to resolve includes.</li>
 * <li>Extensions can not target containers *after* they are resolved. For
 * example, an extension can not target a shared group after it has been
 * included in a page. It can target the initial shared group as a path, but not
 * the group in the page as a path. Again this is because extensions extends
 * anchors that already have a path, not a resolved path.</li>
 * <li>Pages and shared groups that are contributed through extensions become
 * children of the atrget configuration, and so any includes they may have will
 * be resolved correctly.</li>
 * <li>An infinite loop can occur if page A includes from page B and page B in
 * turn includes from page A. iue: cyclic includes. For performnace, accept.
 * </li>
 * <li>When resolving includes, if the target is a container, it must be
 * resolved to resolve its includes correctly. Otherwise, included includes will
 * fail due to reparenting.</li>
 * <li>unresolved includes are left as children of the parent container.</li>
 * <li>Unresolved extensions are left as children of the targetted model.</li>
 * <li>For dynamic awarness, the model is nulled and then reloaded. However, we
 * need to preserve the presentation instance since the UI is already loaded.
 * This is done by reloading the model, and directly resetting the presentation
 * to what it was.</li>
 * <li>Model classes should not have DOM classes as instance vars, and if this
 * is a must, null the DOM class instance the minute you are done. This is
 * because you want the VM to garbage collect the DOM model. Keeping a reference
 * to the DOM model from the Intro model will prevent that.</li>
 * <li>(since 3.0.2) several passes are used to resolve contributions to
 * anchors that themselves where contributed through an extension. Each time a
 * contribution is resolved, the model tries to resolve all unresolved
 * contribution, recursively.
 * </ul>
 * </ol>
 */
public class IntroModelRoot extends AbstractIntroContainer {

    /**
     * Model constants that fire property change event when they are changed in
     * the model.
     */
    public static final int CURRENT_PAGE_PROPERTY_ID = 1;


    private static final String ATT_CONTENT = "content"; //$NON-NLS-1$


    // False if there is no valid contribution to the
    // org.eclipse.ui.into.config extension point. Start off with true, and set
    // to false whenever something bad happens.
    private boolean hasValidConfig = true;
    private boolean isdynamicIntro;
    private IntroPartPresentation introPartPresentation;
    private IntroHomePage homePage;
    private String currentPageId;
    private IntroHomePage standbyPage;


    // the config extensions for this model.
    private IConfigurationElement[] configExtensionElements;

    // a hashtable to hold all loaded DOMs until resolving all configExtensions
    // is done. Key is the extensionContent DOM element, while value is the
    // bundle from where it was loaded.
    private Hashtable unresolvedConfigExt = new Hashtable();

    // maintain listener list for model changes.
    private ListenerList propChangeListeners = new ListenerList(2);

    /**
     * Model root. Takes a configElement that represents <config>in the
     * plugin.xml markup AND all the extension contributed to this model through
     * the configExtension point.
     *  
     */
    public IntroModelRoot(IConfigurationElement configElement,
            IConfigurationElement[] configExtensionElements) {
        // the config element that represents the correct model root.
        super(configElement);
        this.configExtensionElements = configExtensionElements;

    }

    public void loadModel() {
        getChildren();
    }

    /**
     * loads the full model. The children of a model root are the presentation,
     * followed by all pages, and all shared groups. Then if the model has
     * extension, its the unresolved container extensions, followed by all
     * extension pages and groups. The presentation is loaded from the
     * IConfiguration element representing the config. All else is loaded from
     * xml content file.
     *  
     */
    protected void loadChildren() {
        children = new Vector();

        Log.info("Loading Intro plugin model...."); //$NON-NLS-1$

        // load presentation first and create the model class for it. If there
        // is more than one presentation, load first one, and log rest.
        IConfigurationElement presentationElement = loadPresentation();
        if (presentationElement == null) {
            // no presentations at all, exit.
            setModelState(true, false, false);
            Log.warning("Could not find presentation element in intro config."); //$NON-NLS-1$
            return;
        }

        introPartPresentation = new IntroPartPresentation(presentationElement);
        children.add(introPartPresentation);
        // set parent.
        introPartPresentation.setParent(this);

        // now load all children of the config. There should only be pages and
        // groups here. And order is not important. These elements are loaded
        // from the content file DOM.
        Document document = loadDOM(getCfgElement());
        if (document == null) {
            // we failed to parse the content file. Intro Parser would have
            // logged the fact. Parser would also have checked to see if the
            // content file has the correct root tag.
            setModelState(true, false, false);
            return;
        }

        loadPages(document, getBundle());
        loadSharedGroups(document, getBundle());

        // Attributes of root page decide if we have a static or dynamic case.
        setModelState(true, true, getHomePage().isDynamic());
    }

    /**
     * Sets the presentation to the given presentation. The model always has the
     * presentation as the first child, so use that fact. This method is used
     * for dynamic awarness to enable replacing the new presentation with the
     * existing one after a model refresh.
     * 
     * @param presentation
     */
    public void setPresentation(IntroPartPresentation presentation) {
        this.introPartPresentation = presentation;
        presentation.setParent(this);
        children.set(0, presentation);
    }

    /**
     * Resolve contributions into this container's children.
     */
    protected void resolveChildren() {
        // now handle config extension.
        resolveConfigExtensions();
        resolved = true;
    }

    private IConfigurationElement loadPresentation() {
        // If there is more than one presentation, load first one, and log
        // rest.
        IConfigurationElement[] presentationElements = getCfgElement()
                .getChildren(IntroPartPresentation.TAG_PRESENTATION);

        IConfigurationElement presentationElement = ModelLoaderUtil
                .validateSingleContribution(presentationElements,
                        IntroPartPresentation.ATT_HOME_PAGE_ID);
        return presentationElement;
    }



    /**
     * Loads all pages defined in this config from the xml content file.
     */
    private void loadPages(Document dom, Bundle bundle) {
        String homePageId = getPresentation().getHomePageId();
        String standbyPageId = getPresentation().getStandbyPageId();
        Element[] pages = ModelLoaderUtil.getElementsByTagName(dom,
                IntroPage.TAG_PAGE);
        for (int i = 0; i < pages.length; i++) {
            Element pageElement = pages[i];
            if (pageElement.getAttribute(IntroPage.ATT_ID).equals(homePageId)) {
                // Create the model class for the Root Page.
                homePage = new IntroHomePage(pageElement, bundle);
                homePage.setParent(this);
                currentPageId = homePage.getId();
                children.add(homePage);
            } else if (pageElement.getAttribute(IntroPage.ATT_ID).equals(
                    standbyPageId)) {
                // Create the model class for the standby Page.
                standbyPage = new IntroHomePage(pageElement, bundle);
                standbyPage.setParent(this);
                // signal that it is a standby page.
                standbyPage.setStandbyPage(true);
                children.add(standbyPage);
            } else {
                // Create the model class for an intro Page.
                IntroPage page = new IntroPage(pageElement, bundle);
                page.setParent(this);
                children.add(page);
            }
        }
    }

    /**
     * Loads all shared groups defined in this config, from the DOM.
     */
    private void loadSharedGroups(Document dom, Bundle bundle) {
        Element[] groups = ModelLoaderUtil.getElementsByTagName(dom,
                IntroGroup.TAG_GROUP);
        for (int i = 0; i < groups.length; i++) {
            IntroGroup group = new IntroGroup(groups[i], bundle);
            group.setParent(this);
            children.add(group);
        }
    }

    /**
     * Handles all the configExtensions to this current model. Resolving
     * configExts means finding target anchor and inserting extension content at
     * target. Also, several passes are used to resolve as many extensions as
     * possible. This allows for resolving nested anchors (ie: anchors to
     * anchors in contributions).
     *  
     */
    private void resolveConfigExtensions() {
        for (int i = 0; i < configExtensionElements.length; i++)
            resolveConfigExtension(configExtensionElements[i]);
        // now add all unresolved extensions as model children and log fact.
        Enumeration keys = unresolvedConfigExt.keys();
        while (keys.hasMoreElements()) {
            Element configExtensionElement = (Element) keys.nextElement();
            children.add(new IntroExtensionContent(configExtensionElement,
                    (Bundle) unresolvedConfigExt.get(configExtensionElement)));
        }

    }


    private void resolveConfigExtension(IConfigurationElement configExtElement) {
        // get the bundle from the extensions since they are defined in
        // other plugins.
        Bundle bundle = ModelLoaderUtil
                .getBundleFromConfigurationElement(configExtElement);

        Document dom = loadDOM(configExtElement);
        if (dom == null)
            // we failed to parse the content file. Intro Parser would
            // have logged the fact. Parser would also have checked to
            // see if the content file has the correct root tag.
            return;
        else
            resolveConfigExtension(dom, bundle);
    }


    private void resolveConfigExtension(Document dom, Bundle bundle) {
        // Find the target of this container extension, and add all its
        // children to target. Make sure to pass bundle to propagate to all
        // children.
        Element extensionContentElement = loadExtensionContent(dom, bundle);
        if (extensionContentElement == null)
            // no extension content defined, ignore extension completely.
            return;

        if (extensionContentElement.hasAttribute("failed")) { //$NON-NLS-1$
            // we failed to resolve this configExtension, because target
            // could not be found or is not an anchor, add the extension
            // as an (unresolved) child of this model.

            //   children.add(new
            // IntroExtensionContent(extensionContentElement,
            //          bundle));
            if (!unresolvedConfigExt.containsKey(extensionContentElement))
                unresolvedConfigExt.put(extensionContentElement, bundle);

            return;
        }

        // We resolved a contribution. Now load all pages and shared groups
        // from this config extension. No point adding pages that will never
        // be referenced.
        Element[] pages = ModelLoaderUtil.getElementsByTagName(dom,
                IntroPage.TAG_PAGE);
        for (int j = 0; j < pages.length; j++) {
            // Create the model class for an intro Page.
            IntroPage page = new IntroPage(pages[j], bundle);
            page.setParent(this);
            children.add(page);
        }

        // load all shared groups from all configExtensions to this model.
        loadSharedGroups(dom, bundle);

        // since we resolved a contribution, try resolving some of the
        // unresolved ones before going on.
        unresolvedConfigExt.remove(extensionContentElement);
        tryResolvingExtensions();
    }



    /**
     * load the extension content of this configExtension into model classes,
     * and insert them at target. A config extension can have only ONE extension
     * content. This is because if the extension fails, we need to be able to
     * not include the page and group contributions as part of the model.
     * 
     * @param
     * @return
     */
    private Element loadExtensionContent(Document dom, Bundle bundle) {
        Element[] extensionContents = ModelLoaderUtil.getElementsByTagName(dom,
                IntroExtensionContent.TAG_CONTAINER_EXTENSION);
        // There should only be one container extension.
        Element extensionContentElement = ModelLoaderUtil
                .validateSingleContribution(extensionContents,
                        IntroExtensionContent.ATT_PATH);
        if (extensionContentElement == null)
            // no extensionContent defined.
            return null;

        // Create the model class.
        IntroExtensionContent extensionContent = new IntroExtensionContent(
                extensionContentElement, bundle);
        // now resolve this extension.
        String path = extensionContent.getPath();
        AbstractIntroElement target = findTarget(this, path);
        if (target == null || !target.isOfType(AbstractIntroElement.ANCHOR))
            // target could not be found. Signal failure.
            extensionContentElement.setAttribute("failed", "true"); //$NON-NLS-1$ //$NON-NLS-2$
        else {
            // extensions are only for anchors. Insert all children of this
            // extension before this anchor. Anchors need to stay as model
            // children, even after all extensions have been
            // resolved, to enable other plugins to contribute.
            IntroAnchor targetAnchor = (IntroAnchor) target;
            insertAnchorChildren(targetAnchor, extensionContent, bundle);
            handleExtensionStyleInheritence(targetAnchor, extensionContent);
            // make sure to remove failed flag otherwise recursive resolving
            // will not owrk.
            extensionContentElement.removeAttribute("failed");
        }
        return extensionContentElement;
    }


    private void tryResolvingExtensions() {
        Enumeration keys = unresolvedConfigExt.keys();
        while (keys.hasMoreElements()) {
            Element configExtensionElement = (Element) keys.nextElement();
            resolveConfigExtension(configExtensionElement.getOwnerDocument(),
                    (Bundle) unresolvedConfigExt.get(configExtensionElement));
        }
    }


    private void insertAnchorChildren(IntroAnchor anchor,
            IntroExtensionContent extensionContent, Bundle bundle) {
        AbstractIntroContainer anchorParent = (AbstractIntroContainer) anchor
                .getParent();
        // insert the elements of the extension before the anchor.
        anchorParent.insertElementsBefore(extensionContent.getChildren(),
                bundle, anchor);
    }


    /**
     * Updates the inherited styles based on the merge-style attribute. If we
     * are extending a shared group do nothing. For inherited alt-styles, we
     * have to cache the bundle from which we inherited the styles to be able to
     * access resources in that plugin.
     * 
     * @param include
     * @param target
     */
    private void handleExtensionStyleInheritence(IntroAnchor anchor,
            IntroExtensionContent extension) {

        AbstractIntroContainer targetContainer = (AbstractIntroContainer) anchor
                .getParent();
        if (targetContainer.getType() == AbstractIntroElement.GROUP
                && targetContainer.getParent().getType() == AbstractIntroElement.MODEL_ROOT)
            // if we are extending a shared group, defined under a config, we
            // can not include styles.
            return;

        // Update the parent page styles. skip style if it is null;
        String style = extension.getStyle();
        if (style != null)
            targetContainer.getParentPage().addStyle(style);

        // for alt-style cache bundle for loading resources.
        style = extension.getAltStyle();
        if (style != null) {
            Bundle bundle = extension.getBundle();
            targetContainer.getParentPage().addAltStyle(style, bundle);
        }
    }



    /**
     * Sets the model state based on all the model classes. Dynamic nature of
     * the model is always setto false when we fail to load model for any
     * reason.
     */
    private void setModelState(boolean loaded, boolean hasValidConfig,
            boolean isdynamicIntro) {
        this.loaded = loaded;
        this.hasValidConfig = hasValidConfig;
        this.isdynamicIntro = isdynamicIntro;
    }

    /**
     * Returns true if there is a valid contribution to
     * org.eclipse.ui.intro.config extension point, with a valid Presentation,
     * and pages.
     * 
     * @return Returns the hasValidConfig.
     */
    public boolean hasValidConfig() {
        return hasValidConfig;
    }

    /**
     * @return Returns the introPartPresentation.
     */
    public IntroPartPresentation getPresentation() {
        return introPartPresentation;
    }

    /**
     * @return Returns the rootPage.
     */
    public IntroHomePage getHomePage() {
        return homePage;
    }

    /**
     * @return Returns the standby Page. May return null if standby page is not
     *               defined.
     */
    public IntroHomePage getStandbyPage() {
        return standbyPage;
    }

    /**
     * @return all pages *excluding* the Home Page. If all pages are needed,
     *               call <code>(AbstractIntroPage[])
     *         getChildrenOfType(IntroElement.ABSTRACT_PAGE);</code>
     */
    public IntroPage[] getPages() {
        return (IntroPage[]) getChildrenOfType(AbstractIntroElement.PAGE);
    }

    /**
     * @return Returns the isLoaded.
     */
    public boolean isLoaded() {
        return loaded;
    }

    /**
     * @return Returns the isdynamicIntro.
     */
    public boolean isDynamic() {
        return isdynamicIntro;
    }

    /**
     * @return Returns the currentPageId.
     */
    public String getCurrentPageId() {
        return currentPageId;
    }


    /**
     * Sets the current page. If the model does not have a page with the passed
     * id, the message is logged, and the model retains its old current page.
     * 
     * @param currentPageId
     *                   The currentPageId to set. *
     * @param fireEvent
     *                   flag to indicate if event notification is needed.
     * @return true if the model has a page with the passed id, false otherwise.
     *               If the method fails, the current page remains the same as the
     *               last state.
     */
    public boolean setCurrentPageId(String pageId, boolean fireEvent) {
        if (pageId == currentPageId)
            // setting to the same page does nothing. Return true because we did
            // not actually fail. just a no op.
            return true;

        AbstractIntroPage page = (AbstractIntroPage) findChild(pageId,
                ABSTRACT_PAGE);
        if (page == null) {
            // not a page. Test for root page.
            if (!pageId.equals(homePage.getId())) {
                // not a page nor the home page.
                Log.warning("Could not find Intro page with id: " + pageId); //$NON-NLS-1$
                return false;
            }
        }

        currentPageId = pageId;
        if (fireEvent)
            firePropertyChange(CURRENT_PAGE_PROPERTY_ID);
        return true;
    }

    public boolean setCurrentPageId(String pageId) {
        return setCurrentPageId(pageId, true);
    }

    public void addPropertyListener(IPropertyListener l) {
        propChangeListeners.add(l);
    }

    /**
     * Fires a property changed event. Made public because it can be used to
     * trigger a UI refresh.
     * 
     * @param propertyId
     *                   the id of the property that changed
     */
    public void firePropertyChange(final int propertyId) {
        Object[] array = propChangeListeners.getListeners();
        for (int i = 0; i < array.length; i++) {
            final IPropertyListener l = (IPropertyListener) array[i];
            Platform.run(new SafeRunnable() {

                public void run() {
                    l.propertyChanged(this, propertyId);
                }

                public void handleException(Throwable e) {
                    super.handleException(e);
                    //If an unexpected exception happens, remove it
                    //to make sure the workbench keeps running.
                    propChangeListeners.remove(l);
                }
            });
        }
    }

    public void removePropertyListener(IPropertyListener l) {
        propChangeListeners.remove(l);
    }

    /**
     * @return Returns the currentPage. return null if page is not found, or if
     *               we are not in a dynamic intro mode.
     */
    public AbstractIntroPage getCurrentPage() {
        if (!isdynamicIntro)
            return null;

        AbstractIntroPage page = (AbstractIntroPage) findChild(currentPageId,
                ABSTRACT_PAGE);
        if (page != null)
            return page;
        // not a page. Test for root page.
        if (currentPageId.equals(homePage.getId()))
            return homePage;
        // return null if page is not found.
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.internal.intro.impl.model.IntroElement#getType()
     */
    public int getType() {
        return AbstractIntroElement.MODEL_ROOT;
    }


    /**
     * Assumes that the passed config element has a "content" attribute. Reads
     * it and loads a DOM based on that attribute value.
     * 
     * @return
     */
    protected Document loadDOM(IConfigurationElement cfgElement) {
        String content = cfgElement.getAttribute(ATT_CONTENT);
        // Resolve.
        content = IntroModelRoot.getPluginLocation(content, cfgElement);
        Document document = new IntroContentParser(content).getDocument();
        return document;
    }



    /*
     * ======================= Util Methods for Model. =======================
     */

    /**
     * Checks to see if the passed string is a valid URL (has a protocol), if
     * yes, returns it as is. If no, treats it as a resource relative to the
     * declaring plugin. Return the plugin relative location, fully qualified.
     * Retruns null if the passed string itself is null.
     * 
     * @param resource
     * @param pluginDesc
     * @return returns the URL as is if it had a protocol.
     */
    protected static String resolveURL(String url, String pluginId) {
        Bundle bundle = null;
        if (pluginId != null)
            // if pluginId is not null, use it.
            bundle = Platform.getBundle(pluginId);
        return resolveURL(url, bundle);
    }

    /**
     * Checks to see if the passed string is a valid URL (has a protocol), if
     * yes, returns it as is. If no, treats it as a resource relative to the
     * declaring plugin. Return the plugin relative location, fully qualified.
     * Retruns null if the passed string itself is null.
     * 
     * @param resource
     * @param pluginDesc
     * @return returns the URL as is if it had a protocol.
     */
    protected static String resolveURL(String url, IConfigurationElement element) {
        Bundle bundle = ModelLoaderUtil
                .getBundleFromConfigurationElement(element);
        return resolveURL(url, bundle);
    }

    /**
     * @see resolveURL(String url, IConfigurationElement element)
     */
    protected static String resolveURL(String url, Bundle bundle) {
        // quick exit
        if (url == null)
            return null;
        IntroURLParser parser = new IntroURLParser(url);
        if (parser.hasProtocol())
            return url;
        else
            // make plugin relative url. Only now we need the pd.
            return getPluginLocation(url, bundle);
    }



    /**
     * Returns the fully qualified location of the passed resource string from
     * the declaring plugin. If the file could not be loaded from the plugin,
     * the resource is returned as is.
     * 
     * @param resource
     * @return
     */
    public static String getPluginLocation(String resource,
            IConfigurationElement element) {
        Bundle bundle = ModelLoaderUtil
                .getBundleFromConfigurationElement(element);
        return getPluginLocation(resource, bundle);
    }

    public static String getPluginLocation(String resource, Bundle bundle) {

        // quick exits.
        if (resource == null || !ModelLoaderUtil.bundleHasValidState(bundle))
            return null;

        URL localLocation = null;
        try {
            // we need to perform a 'resolve' on this URL.
            localLocation = Platform.find(bundle, new Path(resource));
            if (localLocation == null) {
                // localLocation can be null if the passed resource could not
                // be found relative to the plugin. log fact, return resource,
                // as is.
                String msg = StringUtil.concat("Could not find resource: ", //$NON-NLS-1$
                        resource, " in ", ModelLoaderUtil.getBundleHeader( //$NON-NLS-1$
                                bundle, Constants.BUNDLE_NAME)).toString();
                Log.warning(msg);
                return resource;
            }
            localLocation = Platform.asLocalURL(localLocation);
            return localLocation.toExternalForm();
        } catch (Exception e) {
            String msg = StringUtil.concat("Failed to load resource: ", //$NON-NLS-1$
                    resource, " from ", ModelLoaderUtil.getBundleHeader(bundle, //$NON-NLS-1$
                            Constants.BUNDLE_NAME)).toString();
            Log.error(msg, e);
            return resource;
        }
    }

    /**
     * Returns the fully qualified location of the passed resource string from
     * the passed plugin id. If the file could not be loaded from the plugin,
     * the resource is returned as is.
     * 
     * @param resource
     * @return
     */
    public static String getPluginLocation(String resource, String pluginId) {
        Bundle bundle = Platform.getBundle(pluginId);
        return getPluginLocation(resource, bundle);
    }



}