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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.help.UAContentFilter;
import org.eclipse.help.internal.UAElementFactory;
import org.eclipse.help.internal.util.ProductPreferences;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.internal.intro.impl.FontSelection;
import org.eclipse.ui.internal.intro.impl.IntroPlugin;
import org.eclipse.ui.internal.intro.impl.model.loader.IntroContentParser;
import org.eclipse.ui.internal.intro.impl.model.loader.ModelLoaderUtil;
import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
import org.eclipse.ui.internal.intro.impl.model.util.ModelUtil;
import org.eclipse.ui.internal.intro.impl.util.IntroEvaluationContext;
import org.eclipse.ui.internal.intro.impl.util.Log;
import org.eclipse.ui.internal.intro.impl.util.StringUtil;
import org.eclipse.ui.intro.config.IntroConfigurer;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * The root class for the OOBE model. It loads the configuration into the
 * appropriate classes.
 *
 * Model rules:
 * <ol>
 * <li>if an attribute is not included in the markup, its value will be null in
 * the model.</li>
 * <li>Resources in plugin.xml are not implicitly resolved against $nl$.
 * Resources in pages are implicitly resolved against $nl$
 * <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. ie: 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>
 * </ol>
 * <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>
 */
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$
    private static final String ATT_CONFIGURER = "configurer"; //$NON-NLS-1$
    private static final String VAR_THEME = "theme";  //$NON-NLS-1$
    private static final String VAR_DIRECTION = "direction";  //$NON-NLS-1$

    // False if there is no valid contribution to the
    // org.eclipse.ui.intro.config extension point. Start off with true, and set
    // to false whenever something bad happens.
    private boolean hasValidConfig = true;
    private IntroConfigurer configurer;
    private IntroTheme theme;
    private IntroPartPresentation introPartPresentation;
    private IntroHomePage rootPage;
    private String currentPageId;
    private String startPageId;
    private AbstractIntroPage standbyPage;
    private AbstractIntroPage homePage;
	private String modelStandbyPageId;

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

    // maintain listener list for model changes.
	public ListenerList<IPropertyListener> propChangeListeners = new ListenerList<>();

    // a list to hold all loaded DOMs until resolving all configExtensions
    // is done.
	private List<ExtensionContent> unresolvedConfigExt = new ArrayList<>();


    private class ExtensionContent {
    	Element element;
        IConfigurationElement configExtElement;
        ExtensionContent(Element element,
                IConfigurationElement configExtElement) {
            this.element = element;
            this.configExtElement = configExtElement;
        }
    }

    /**
     * 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();
        determineHomePage();
    }

    /**
     * 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.
     *
     */
    @Override
	protected void loadChildren() {
		children = new Vector<>();
        if (Log.logInfo)
            Log.info("Creating 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);
            Log.warning("Could not find presentation element in intro config."); //$NON-NLS-1$
            return;
        }

        loadTheme();
        loadConfigurer();

        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);
            return;
        }

        // set base for this model.
        this.base = getBase(getCfgElement());

        // now load content.
        loadPages(document, getBundle());
        loadSharedGroups(document, getBundle());

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

		if (configurer != null) {
			// The configurer may vary its returned results based on the theme
			// properties
			configurer.bind(this);
		}
    }

    /**
     * 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.
     */
    @Override
	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;
    }

    private void loadConfigurer() {
    	String cname = getCfgElement().getAttribute(ATT_CONFIGURER);
    	if (cname!=null) {
    		try {
    			Object obj = getCfgElement().createExecutableExtension(ATT_CONFIGURER);
				if (obj instanceof IntroConfigurer) {
    				configurer = (IntroConfigurer)obj;
				}
    		}
    		catch (CoreException e) {
    			Log.error("Error loading intro configurer", e); //$NON-NLS-1$
    		}
    	}
    }

    private void determineHomePage() {
    	String pid = Platform.getProduct().getId();
    	startPageId = getProcessPreference("INTRO_START_PAGE", pid); //$NON-NLS-1$
    	String homePagePreference = getProcessPreference("INTRO_HOME_PAGE", pid); //$NON-NLS-1$
    	homePage = rootPage;  // Default, may be overridden
    	if (homePagePreference.length() != 0) {
    		AbstractIntroPage page = (AbstractIntroPage) findChild(homePagePreference,
    	            ABSTRACT_PAGE);
    		if (page != null) {
    			homePage = page;
    		    if(startPageId.length() == 0) {
    			    startPageId = homePagePreference;
    		    }
    		}
    	}
    	String standbyPagePreference = getProcessPreference("INTRO_STANDBY_PAGE", pid); //$NON-NLS-1$
        modelStandbyPageId = getPresentation().getStandbyPageId();

        if (standbyPagePreference.length() != 0) {
        	standbyPage = (AbstractIntroPage) findChild(standbyPagePreference,
    	            ABSTRACT_PAGE);
        }
        if (standbyPage == null && modelStandbyPageId != null && modelStandbyPageId.length() != 0) {
        	standbyPage = (AbstractIntroPage) findChild(modelStandbyPageId,
    	            ABSTRACT_PAGE);
        }
        if (standbyPage != null) {
            standbyPage.setStandbyPage(true);
        }
    }

    private void loadTheme() {
    	String pid = Platform.getProduct().getId();
    	String themeId = getProcessPreference("INTRO_THEME", pid); //$NON-NLS-1$

    	IConfigurationElement [] elements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.ui.intro.configExtension"); //$NON-NLS-1$
    	IConfigurationElement themeElement=null;
    	for (int i=0; i<elements.length; i++) {
    		if (elements[i].getName().equals("theme")) { //$NON-NLS-1$
    			String id = elements[i].getAttribute("id"); //$NON-NLS-1$
    			if (themeId!=null) {
    				if (id!=null && themeId.equals(id)) {
    					// use this one
    					themeElement = elements[i];
    					break;
    				}
    			}
    			else {
    				// see if this one is the default
    				String value = elements[i].getAttribute("default"); //$NON-NLS-1$
    				if (value!=null && value.equalsIgnoreCase("true")) { //$NON-NLS-1$
    					themeElement = elements[i];
    					break;
    				}
    			}
    		}
    	}
    	if (themeElement!=null) {
    		theme = new IntroTheme(themeElement);
    	}
    }

    /**
     * Loads all pages defined in this config from the xml content file.
     */
    private void loadPages(Document dom, Bundle bundle) {
        String rootPageId = getPresentation().getHomePageId();
        Element[] pages = ModelUtil.getElementsByTagName(dom,
            AbstractIntroPage.TAG_PAGE);
        for (int i = 0; i < pages.length; i++) {
            Element pageElement = pages[i];
            if (pageElement.getAttribute(AbstractIntroIdElement.ATT_ID).equals(
                rootPageId)) {
                // Create the model class for the Root Page.
                rootPage = new IntroHomePage(pageElement, bundle, base);
                rootPage.setParent(this);
                currentPageId = rootPage.getId();
                children.add(rootPage);
            } else {
                // Create the model class for an intro Page.
                IntroPage page = new IntroPage(pageElement, bundle, base);
                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 = ModelUtil.getElementsByTagName(dom,
            IntroGroup.TAG_GROUP);
        for (int i = 0; i < groups.length; i++) {
            IntroGroup group = new IntroGroup(groups[i], bundle, base);
            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++) {
            processConfigExtension(configExtensionElements[i]);
        }

        tryResolvingExtensions();

        // At this stage all pages will be resolved, some contributions may not be

        // now add all unresolved extensions as model children and log fact.
        Iterator keys = unresolvedConfigExt.iterator();
        while (keys.hasNext()) {
            ExtensionContent extension = (ExtensionContent) keys.next();
            Element configExtensionElement = extension.element;
            IConfigurationElement configExtConfigurationElement = extension.configExtElement;
            Bundle bundle = BundleUtil
                .getBundleFromConfigurationElement(configExtConfigurationElement);
            String base = getBase(configExtConfigurationElement);
            children.add(new IntroExtensionContent(configExtensionElement,
                bundle, base, configExtConfigurationElement));

            // INTRO: fix log strings.
            Log
                .warning("Could not resolve the following configExtension: " //$NON-NLS-1$
                        + ModelLoaderUtil.getLogString(bundle,
                            configExtensionElement,
                            IntroExtensionContent.ATT_PATH));
        }
    }

    private void processConfigExtension(IConfigurationElement configExtElement) {
        // This call will extract the parent folder if needed.
        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;
        processConfigExtension(dom, configExtElement);
    }


    private void processConfigExtension(Document dom,
            IConfigurationElement configExtElement) {

        // Find the target of this container extension, and add all its
        // children to target. Make sure to pass correct bundle and base to
        // propagate to all children.
        String base = getBase(configExtElement);
        Element[] extensionContentElements = loadExtensionContent(dom,
            configExtElement, base);
        for (int i = 0; i < extensionContentElements.length; i++) {
        	Element extensionContentElement = extensionContentElements[i];
             unresolvedConfigExt.add(new ExtensionContent(extensionContentElement,
                         configExtElement));
        }

        // Now load all pages and shared groups
        // from this config extension. Get the bundle from the extensions since they are
        // defined in other plugins.
        Bundle bundle = BundleUtil
            .getBundleFromConfigurationElement(configExtElement);

        Element[] pages = ModelUtil.getElementsByTagName(dom,
            AbstractIntroPage.TAG_PAGE);
        for (int j = 0; j < pages.length; j++) {
            // Create the model class for an intro Page.
        	if (!UAContentFilter.isFiltered(UAElementFactory.newElement(pages[j]), IntroEvaluationContext.getContext())) {
                IntroPage page = new IntroPage(pages[j], bundle, base);
                page.setParent(this);
                children.add(page);
        	}
        }
    }

    private void tryResolvingExtensions() {
    	int previousSize;
    	do {
    		previousSize = unresolvedConfigExt.size();
			List<ExtensionContent> stillUnresolved = new ArrayList<>();
			for (ExtensionContent content : unresolvedConfigExt) {
                Element extensionContentElement = content.element;
                IConfigurationElement configExtElement = content.configExtElement;
				Bundle bundle = BundleUtil.getBundleFromConfigurationElement(configExtElement);
				String elementBase = getBase(configExtElement);
                processOneExtension(configExtElement, elementBase, bundle, extensionContentElement);
				if (extensionContentElement.hasAttribute("failed")) { //$NON-NLS-1$
					stillUnresolved.add(content);
				}
            }
            unresolvedConfigExt = stillUnresolved;
        } while (unresolvedConfigExt.size() < previousSize);
    }

    /**
     * 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. If
     * extension content has XHTML content (ie: content attribute is defined) we
     * load extension DOM into target page dom.
     *
     * note: the extension Element is returned to enable creating a child model
     * element on failure.
     *
     * @param
     * @return
     */
    private Element[] loadExtensionContent(Document dom,
            IConfigurationElement configExtElement, String base) {

        // get the bundle from the extensions since they are defined in
        // other plugins.
		List<Element> elements = new ArrayList<>();
        Element[] extensionContents = ModelUtil.getElementsByTagName(dom,
            IntroExtensionContent.TAG_CONTAINER_EXTENSION);
        Element[] replacementContents =	 ModelUtil.getElementsByTagName(dom,
        			IntroExtensionContent.TAG_CONTAINER_REPLACE);

        addUnfilteredExtensions(elements, extensionContents);
        addUnfilteredExtensions(elements, replacementContents);

        return (Element[])elements.toArray(new Element[elements.size()]);
    }

	private void addUnfilteredExtensions(List<Element> elements, Element[] extensionContents) {
		for (int i = 0; i < extensionContents.length; i++) {
        	Element extensionContentElement = extensionContents[i];
        	if (!UAContentFilter.isFiltered(UAElementFactory.newElement(extensionContentElement), IntroEvaluationContext.getContext())) {
        	    elements.add(extensionContentElement);
            }
        }
	}

	private void processOneExtension(IConfigurationElement configExtElement, String base, Bundle bundle,
			Element extensionContentElement) {
		// Create the model class for extension content.
		IntroExtensionContent extensionContent = new IntroExtensionContent(
		    extensionContentElement, bundle, base, configExtElement);
		boolean success = false;
		if (extensionContent.isXHTMLContent())
		    success = loadXHTMLExtensionContent(extensionContent);
		else
		    success = load3_0ExtensionContent(extensionContent);

		if (success) {
		    if (extensionContentElement.hasAttribute("failed")) //$NON-NLS-1$
		        extensionContentElement.removeAttribute("failed"); //$NON-NLS-1$
		} else
		    extensionContentElement.setAttribute("failed", "true"); //$NON-NLS-1$ //$NON-NLS-2$
	}


    /**
     * Insert the extension content into the target.
     *
     * @param extensionContent
     * @return
     */
    private boolean loadXHTMLExtensionContent(
            IntroExtensionContent extensionContent) {
        String path = extensionContent.getPath();
        // path must be pageId/anchorID in the case of anchors in XHTML pages.
        String[] pathSegments = StringUtil.split(path, "/"); //$NON-NLS-1$
        if (pathSegments.length != 2)
            // path does not have correct format.
            return false;
        AbstractIntroPage targetPage = (AbstractIntroPage) findChild(
            pathSegments[0], ABSTRACT_PAGE);
        if (targetPage == null)
            // target could not be found. Signal failure.
            return false;

        // Insert all children of this extension before the target element. Anchors need
        // to stay in DOM, even after all extensions have been resolved, to enable other
        // plugins to contribute. Find the target node.
        Document pageDom = targetPage.getDocument();
        Element targetElement = targetPage.findDomChild(pathSegments[1], "*"); //$NON-NLS-1$
        if (targetElement == null)
            return false;

        // get extension content
        Element[] elements = extensionContent.getElements();
        // insert all children before anchor in page body.
        for (int i = 0; i < elements.length; i++) {
            Node targetNode = pageDom.importNode(elements[i], true);
            // update the src attribute of this node, if defined by w3
            // specs.

            ModelUtil.updateResourceAttributes((Element) targetNode,
                extensionContent);
            targetElement.getParentNode().insertBefore(targetNode, targetElement);
        }

        if (extensionContent.getExtensionType() == IntroExtensionContent.TYPE_REPLACEMENT) {
            targetElement.getParentNode().removeChild(targetElement);
        }

        // now handle style inheritance.
        // Update the parent page styles. skip style if it is null;
        String[] styles = extensionContent.getStyles();
        if (styles != null) {
            for (int i = 0; i < styles.length; i++)
                ModelUtil.insertStyle(pageDom, styles[i]);
        }

        return true;

    }



    /**
     * Insert the extension content (3.0 format) into the target.
     *
     * @param extensionContent
     * @return
     */
    private boolean load3_0ExtensionContent(IntroExtensionContent extensionContent) {
        String path = extensionContent.getPath();
        int type = extensionContent.getExtensionType();
        AbstractIntroElement target = findTarget(this, path, extensionContent.getId());
        if (target != null && target.isOfType(AbstractIntroElement.ANCHOR) == (type == IntroExtensionContent.TYPE_CONTRIBUTION)) {
        	// insert all children of this extension before the target element/anchor.
	        insertExtensionChildren(target, extensionContent, extensionContent.getBundle(), extensionContent.getBase());
	        // anchors need to stay around to receive other contributions
	        if (type == IntroExtensionContent.TYPE_REPLACEMENT) {
	        	AbstractIntroContainer parent = (AbstractIntroContainer)target.getParent();
	        	parent.removeChild(target);
	        }
	        handleExtensionStyleInheritence(target, extensionContent);
	        return true;
        }
        // appropriate target could not be found. Signal failure.
        return false;
    }

    private void insertExtensionChildren(AbstractIntroElement target,
            IntroExtensionContent extensionContent, Bundle bundle, String base) {
        AbstractIntroContainer parent = (AbstractIntroContainer)target.getParent();
        // insert the elements of the extension before the target
        String mixinStyle = getMixinStyle(extensionContent);
        Element [] children = extensionContent.getChildren();
        parent.insertElementsBefore(children, bundle, base, target, mixinStyle);
    }

    private String getMixinStyle(IntroExtensionContent extensionContent) {
    	String path = extensionContent.getPath();
    	if (!path.endsWith("/@")) //$NON-NLS-1$
    		return null;
    	String pageId = path.substring(0, path.length()-2);
    	IntroModelRoot modelRoot = getModelRoot();
    	if (modelRoot==null)
    		return null;
    	IntroConfigurer configurer = modelRoot.getConfigurer();
    	if (configurer==null)
    		return null;
    	String extensionId = extensionContent.getId();
    	// if this is a replace, take the mixin style as what is being replaced
    	if (extensionContent.getExtensionType() == IntroExtensionContent.TYPE_REPLACEMENT) {
    		IPath ipath = new Path(extensionContent.getPath());
    		String s2 = ipath.segment(1);
    		if (s2 != null && s2.startsWith("@") && s2.length() > 1) { //$NON-NLS-1$
    			extensionId = s2.substring(1);
    		}
    	}
   		return configurer.getMixinStyle(pageId, extensionId);
    }


    /**
     * Updates the inherited styles based on the style attribtes defined in the
     * configExtension. 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(AbstractIntroElement target,
            IntroExtensionContent extension) {

        AbstractIntroContainer targetContainer = (AbstractIntroContainer)target.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[] styles = extension.getStyles();
        if (styles != null)
            targetContainer.getParentPage().addStyles(styles);

        // for alt-style cache bundle for loading resources.
		Map<String, Bundle> altStyles = extension.getAltStyles();
        if (altStyles != null)
            targetContainer.getParentPage().addAltStyles(altStyles);
    }

    /**
     * Sets the model state based on all the model classes.
     */
    private void setModelState(boolean loaded, boolean hasValidConfig) {
        this.loaded = loaded;
        this.hasValidConfig = hasValidConfig;
    }

    /**
     * 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;
    }

    public IntroConfigurer getConfigurer() {
    	return configurer;
    }

    /**
     * @return Returns the home Page.
     */
    public AbstractIntroPage getHomePage() {
        return homePage;
    }

    /**
     * @return Returns the root Page.
     */
    public IntroHomePage getRootPage() {
        return rootPage;
    }

    /**
     * @return Returns the standby Page. May return null if standby page is not
     *         defined.
     */
    public AbstractIntroPage 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 isdynamicIntro.
     */
    public boolean isDynamic() {
        if ("swt".equals(getPresentation().getImplementationKind())) { //$NON-NLS-1$
        	return rootPage != null && rootPage.isDynamic();
        }
        return true;
    }

    /**
     * @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.equals(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(rootPage.getId())) {
                // not a page nor the home page.
                Log
                    .warning("Could not set current page to 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];
            SafeRunner.run(new SafeRunnable() {

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

                @Override
				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 (!isDynamic())
            return null;
        AbstractIntroPage page = (AbstractIntroPage) findChild(currentPageId,
            ABSTRACT_PAGE);
        if (page != null)
            return page;
        // not a page. Test for root page.
        if (currentPageId.equals(rootPage.getId()))
            return rootPage;
        // return null if page is not found.
        return null;
    }

    @Override
	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. It does not explicitly
     * resolve the resource because this method only loads the introContent and
     * the configExt content files. ie: in plugin.xml. <br>
     * This method also sets the base attribute on the root element in the DOM
     * to enable resolving all resources relative to this DOM.
     *
     * @return
     */
    protected Document loadDOM(IConfigurationElement cfgElement) {
        String content = cfgElement.getAttribute(ATT_CONTENT);

        // To support jarring, extract parent folder of where the intro content
        // file is. It is expected that all intro content is in that one parent
        // folder. This works for both content files and configExtension content
        // files.
        Bundle domBundle = BundleUtil
            .getBundleFromConfigurationElement(cfgElement);
        ModelUtil.ensureFileURLsExist(domBundle, content);

        // Resolve.
        content = BundleUtil.getResourceLocation(content, cfgElement);
        Document document = new IntroContentParser(content).getDocument();

        return document;
    }


    private String getBase(IConfigurationElement configElement) {
        String content = configElement.getAttribute(ATT_CONTENT);
        return ModelUtil.getParentFolderToString(content);
    }

    public String resolveVariables(String text) {
    	if (text==null) return null;
    	if (text.indexOf('$')== -1)
    		return text;
    	// resolve
    	boolean inVariable=false;
    	StringBuffer buf = new StringBuffer();
    	int vindex=0;
    	for (int i=0; i<text.length(); i++) {
    		char c = text.charAt(i);
    		if (c=='$') {
    			if (!inVariable) {
    				inVariable=true;
    				vindex=i+1;
    				continue;
    			}
 				inVariable=false;
   				String variable=text.substring(vindex, i);
   				String value = getVariableValue(variable);
   				if (value==null)
   					value = "$"+variable+"$"; //$NON-NLS-1$ //$NON-NLS-2$
   				buf.append(value);
   				continue;
    		}
    		else if (!inVariable)
    			buf.append(c);
    	}
    	return buf.toString();
    }

    private String getVariableValue(String variable) {
     	if (variable.equals(VAR_THEME)) {
    		if (theme!=null)
    			return theme.getPath();
    	}
     	if (variable.equals(FontSelection.VAR_FONT_STYLE)) {
     		return FontSelection.getFontStyle();
    	}
     	if (variable.equals(VAR_DIRECTION)) {
    		if (ProductPreferences.isRTL()) {
    			return "rtl"; //$NON-NLS-1$
    		} else {
    			return "ltr"; //$NON-NLS-1$
    		}
    	}

    	if (configurer!=null)
    		return configurer.getVariable(variable);
    	return null;
    }

    public String resolvePath(String extensionId, String path) {
    	if (configurer==null) return null;
    	return configurer.resolvePath(extensionId, path);
    }


	public IntroTheme getTheme() {
		return theme;
	}

	public String getStartPageId() {
		return startPageId;
	}

	private String getProcessPreference(String key, String pid) {
		String result = Platform.getPreferencesService().getString
		      (IntroPlugin.PLUGIN_ID,  pid + '_' + key, "", null); //$NON-NLS-1$
    	if (result.length() == 0) {
    		result = Platform.getPreferencesService().getString
		        (IntroPlugin.PLUGIN_ID,  key, "", null); //$NON-NLS-1$
    	}
    	return result;
	}
}