/*******************************************************************************
 * Copyright (c) 2000, 2015 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.decorators;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;

/**
 * The RunnableDecoratorDefinition is the definition for
 * decorators that have an ILabelDecorator class to instantiate.
 */

class FullDecoratorDefinition extends DecoratorDefinition {

	ILabelDecorator decorator;

    /**
     * Create a new instance of the receiver with the
     * supplied values.
     */

    FullDecoratorDefinition(String identifier, IConfigurationElement element) {
        super(identifier, element);
    }

    /**
     * Gets the decorator and creates it if it does
     * not exist yet. Throws a CoreException if there is a problem
     * creating the decorator.
     * This method should not be called unless a check for
     * enabled to be true is done first.
     * @return Returns a ILabelDecorator
     */
    protected ILabelDecorator internalGetDecorator() throws CoreException {
        if (labelProviderCreationFailed) {
			return null;
		}

        final CoreException[] exceptions = new CoreException[1];

        if (decorator == null) {
            Platform
                    .run(new SafeRunnable(
                            NLS.bind(WorkbenchMessages.DecoratorManager_ErrorActivatingDecorator, getName() )) {
                        @Override
						public void run() {
                            try {
                                decorator = (ILabelDecorator) WorkbenchPlugin
                                        .createExtension(
                                                definingElement,
                                                DecoratorDefinition.ATT_CLASS);
                                decorator.addListener(WorkbenchPlugin
                                        .getDefault().getDecoratorManager());
                            } catch (CoreException exception) {
                                exceptions[0] = exception;
                            }
                        }
                    });
        } else {
			return decorator;
		}

        if (decorator == null) {
            this.labelProviderCreationFailed = true;
            setEnabled(false);
        }

        if (exceptions[0] != null) {
			throw exceptions[0];
		}

        return decorator;
    }

    @Override
	protected void refreshDecorator() {
        //Only do something if disabled so as to prevent
        //gratutitous activation
        if (!this.enabled && decorator != null) {
            IBaseLabelProvider cached = decorator;
            decorator = null;
            disposeCachedDecorator(cached);
        }
    }

    /**
     * Decorate the image provided for the element type.
     * This method should not be called unless a check for
     * isEnabled() has been done first.
     * Return null if there is no image or if an error occurs.
     */
    Image decorateImage(Image image, Object element) {
        try {
            //Internal decorator might be null so be prepared
            ILabelDecorator currentDecorator = internalGetDecorator();
            if (currentDecorator != null) {
				return currentDecorator.decorateImage(image, element);
			}

        } catch (CoreException exception) {
            handleCoreException(exception);
        }
        return null;
    }

    /**
     * Decorate the text provided for the element type.
     * This method should not be called unless a check for
     * isEnabled() has been done first.
     * Return null if there is no text or if there is an exception.
     */
    String decorateText(String text, Object element) {
        try {
            //Internal decorator might be null so be prepared
            ILabelDecorator currentDecorator = internalGetDecorator();
            if (currentDecorator != null) {
				return currentDecorator.decorateText(text, element);
			}
        } catch (CoreException exception) {
            handleCoreException(exception);
        }
        return null;
    }

    /**
     * Returns the decorator, or <code>null</code> if not enabled.
     *
     * @return the decorator, or <code>null</code> if not enabled
     */
    public ILabelDecorator getDecorator() {
        return decorator;
    }

    @Override
	protected IBaseLabelProvider internalGetLabelProvider()
            throws CoreException {
        return internalGetDecorator();
    }

    @Override
	public boolean isFull() {
        return true;
    }

}
