/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.eclipse.org/org/documents/epl-v10.php
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;

import static com.android.SdkConstants.LAYOUT_RESOURCE_PREFIX;

import com.android.annotations.NonNull;
import com.android.ide.common.api.IClientRulesEngine;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.Rect;
import com.android.ide.common.rendering.HardwareConfigHelper;
import com.android.ide.common.rendering.LayoutLibrary;
import com.android.ide.common.rendering.RenderSecurityManager;
import com.android.ide.common.rendering.api.AssetRepository;
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.DrawableParams;
import com.android.ide.common.rendering.api.HardwareConfig;
import com.android.ide.common.rendering.api.IImageFactory;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.ide.common.resources.ResourceResolver;
import com.android.ide.common.resources.configuration.FolderConfiguration;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.AdtUtils;
import com.android.ide.eclipse.adt.internal.editors.layout.ContextPullParser;
import com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback;
import com.android.ide.eclipse.adt.internal.editors.layout.UiElementPullParser;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser;
import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Locale;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder.Reference;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy;
import com.android.ide.eclipse.adt.internal.editors.layout.uimodel.UiViewElementNode;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo.ActivityAttributes;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiElementNode;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.devices.Device;
import com.google.common.base.Charsets;
import com.google.common.io.Files;

import org.eclipse.core.resources.IProject;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * The {@link RenderService} provides rendering and layout information for
 * Android layouts. This is a wrapper around the layout library.
 */
public class RenderService {
    private static final Object RENDERING_LOCK = new Object();

    /** Reference to the file being edited. Can also be used to access the {@link IProject}. */
    private final GraphicalEditorPart mEditor;

    // The following fields are inferred from the editor and not customizable by the
    // client of the render service:

    private final IProject mProject;
    private final ProjectCallback mProjectCallback;
    private final ResourceResolver mResourceResolver;
    private final int mMinSdkVersion;
    private final int mTargetSdkVersion;
    private final LayoutLibrary mLayoutLib;
    private final IImageFactory mImageFactory;
    private final HardwareConfigHelper mHardwareConfigHelper;
    private final Locale mLocale;

    // The following fields are optional or configurable using the various chained
    // setters:

    private UiDocumentNode mModel;
    private Reference mIncludedWithin;
    private RenderingMode mRenderingMode = RenderingMode.NORMAL;
    private LayoutLog mLogger;
    private Integer mOverrideBgColor;
    private boolean mShowDecorations = true;
    private Set<UiElementNode> mExpandNodes = Collections.<UiElementNode>emptySet();
    private final Object mCredential;

    /** Use the {@link #create} factory instead */
    private RenderService(GraphicalEditorPart editor, Object credential) {
        mEditor = editor;
        mCredential = credential;

        mProject = editor.getProject();
        LayoutCanvas canvas = editor.getCanvasControl();
        mImageFactory = canvas.getImageOverlay();
        ConfigurationChooser chooser = editor.getConfigurationChooser();
        Configuration config = chooser.getConfiguration();
        FolderConfiguration folderConfig = config.getFullConfig();

        Device device = config.getDevice();
        assert device != null; // Should only attempt render with configuration that has device
        mHardwareConfigHelper = new HardwareConfigHelper(device);
        mHardwareConfigHelper.setOrientation(
                folderConfig.getScreenOrientationQualifier().getValue());

        mLayoutLib = editor.getReadyLayoutLib(true /*displayError*/);
        mResourceResolver = editor.getResourceResolver();
        mProjectCallback = editor.getProjectCallback(true /*reset*/, mLayoutLib);
        mMinSdkVersion = editor.getMinSdkVersion();
        mTargetSdkVersion = editor.getTargetSdkVersion();
        mLocale = config.getLocale();
    }

    private RenderService(GraphicalEditorPart editor,
            Configuration configuration, ResourceResolver resourceResolver,
            Object credential) {
        mEditor = editor;
        mCredential = credential;

        mProject = editor.getProject();
        LayoutCanvas canvas = editor.getCanvasControl();
        mImageFactory = canvas.getImageOverlay();
        FolderConfiguration folderConfig = configuration.getFullConfig();

        Device device = configuration.getDevice();
        assert device != null;
        mHardwareConfigHelper = new HardwareConfigHelper(device);
        mHardwareConfigHelper.setOrientation(
                folderConfig.getScreenOrientationQualifier().getValue());

        mLayoutLib = editor.getReadyLayoutLib(true /*displayError*/);
        mResourceResolver =  resourceResolver != null ? resourceResolver : editor.getResourceResolver();
        mProjectCallback = editor.getProjectCallback(true /*reset*/, mLayoutLib);
        mMinSdkVersion = editor.getMinSdkVersion();
        mTargetSdkVersion = editor.getTargetSdkVersion();
        mLocale = configuration.getLocale();
    }

    private RenderSecurityManager createSecurityManager() {
        String projectPath = null;
        String sdkPath = null;
        if (RenderSecurityManager.RESTRICT_READS) {
            projectPath = AdtUtils.getAbsolutePath(mProject).toFile().getPath();
            Sdk sdk = Sdk.getCurrent();
            sdkPath = sdk != null ? sdk.getSdkOsLocation() : null;
        }
        RenderSecurityManager securityManager = new RenderSecurityManager(sdkPath, projectPath);
        securityManager.setLogger(AdtPlugin.getDefault());

        // Make sure this is initialized before we attempt to use it from layoutlib
        Toolkit.getDefaultToolkit();

        return securityManager;
      }

    /**
     * Returns true if this configuration supports the given rendering
     * capability
     *
     * @param target the target to look up the layout library for
     * @param capability the capability to check
     * @return true if the capability is supported
     */
    public static boolean supports(
            @NonNull IAndroidTarget target,
            @NonNull Capability capability) {
        Sdk sdk = Sdk.getCurrent();
        if (sdk != null) {
            AndroidTargetData targetData = sdk.getTargetData(target);
            if (targetData != null) {
                LayoutLibrary layoutLib = targetData.getLayoutLibrary();
                if (layoutLib != null) {
                    return layoutLib.supports(capability);
                }
            }
        }

        return false;
    }

    /**
     * Creates a new {@link RenderService} associated with the given editor.
     *
     * @param editor the editor to provide configuration data such as the render target
     * @return a {@link RenderService} which can perform rendering services
     */
    public static RenderService create(GraphicalEditorPart editor) {
        // Delegate to editor such that it can pass its credential to the service
        return editor.createRenderService();
    }

    /**
     * Creates a new {@link RenderService} associated with the given editor.
     *
     * @param editor the editor to provide configuration data such as the render target
     * @param credential the sandbox credential
     * @return a {@link RenderService} which can perform rendering services
     */
    @NonNull
    public static RenderService create(GraphicalEditorPart editor, Object credential) {
        return new RenderService(editor, credential);
    }

    /**
     * Creates a new {@link RenderService} associated with the given editor.
     *
     * @param editor the editor to provide configuration data such as the render target
     * @param configuration the configuration to use (and fallback to editor for the rest)
     * @param resolver a resource resolver to use to look up resources
     * @return a {@link RenderService} which can perform rendering services
     */
    public static RenderService create(GraphicalEditorPart editor,
            Configuration configuration, ResourceResolver resolver) {
        // Delegate to editor such that it can pass its credential to the service
        return editor.createRenderService(configuration, resolver);
    }

    /**
     * Creates a new {@link RenderService} associated with the given editor.
     *
     * @param editor the editor to provide configuration data such as the render target
     * @param configuration the configuration to use (and fallback to editor for the rest)
     * @param resolver a resource resolver to use to look up resources
     * @param credential the sandbox credential
     * @return a {@link RenderService} which can perform rendering services
     */
    public static RenderService create(GraphicalEditorPart editor,
            Configuration configuration, ResourceResolver resolver, Object credential) {
        return new RenderService(editor, configuration, resolver, credential);
    }

    /**
     * Renders the given model, using this editor's theme and screen settings, and returns
     * the result as a {@link RenderSession}.
     *
     * @param model the model to be rendered, which can be different than the editor's own
     *            {@link #getModel()}.
     * @param width the width to use for the layout, or -1 to use the width of the screen
     *            associated with this editor
     * @param height the height to use for the layout, or -1 to use the height of the screen
     *            associated with this editor
     * @param explodeNodes a set of nodes to explode, or null for none
     * @param overrideBgColor If non-null, use the given color as a background to render over
     *        rather than the normal background requested by the theme
     * @param noDecor If true, don't draw window decorations like the system bar
     * @param logger a logger where rendering errors are reported
     * @param renderingMode the {@link RenderingMode} to use for rendering
     * @return the resulting rendered image wrapped in an {@link RenderSession}
     */

    /**
     * Sets the {@link LayoutLog} to be used during rendering. If none is specified, a
     * silent logger will be used.
     *
     * @param logger the log to be used
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setLog(LayoutLog logger) {
        mLogger = logger;
        return this;
    }

    /**
     * Sets the model to be rendered, which can be different than the editor's own
     * {@link GraphicalEditorPart#getModel()}.
     *
     * @param model the model to be rendered
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setModel(UiDocumentNode model) {
        mModel = model;
        return this;
    }

    /**
     * Overrides the width and height to be used during rendering (which might be adjusted if
     * the {@link #setRenderingMode(RenderingMode)} is {@link RenderingMode#FULL_EXPAND}.
     *
     * A value of -1 will make the rendering use the normal width and height coming from the
     * {@link Configuration#getDevice()} object.
     *
     * @param overrideRenderWidth the width in pixels of the layout to be rendered
     * @param overrideRenderHeight the height in pixels of the layout to be rendered
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setOverrideRenderSize(int overrideRenderWidth, int overrideRenderHeight) {
        mHardwareConfigHelper.setOverrideRenderSize(overrideRenderWidth, overrideRenderHeight);
        return this;
    }

    /**
     * Sets the max width and height to be used during rendering (which might be adjusted if
     * the {@link #setRenderingMode(RenderingMode)} is {@link RenderingMode#FULL_EXPAND}.
     *
     * A value of -1 will make the rendering use the normal width and height coming from the
     * {@link Configuration#getDevice()} object.
     *
     * @param maxRenderWidth the max width in pixels of the layout to be rendered
     * @param maxRenderHeight the max height in pixels of the layout to be rendered
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setMaxRenderSize(int maxRenderWidth, int maxRenderHeight) {
        mHardwareConfigHelper.setMaxRenderSize(maxRenderWidth, maxRenderHeight);
        return this;
    }

    /**
     * Sets the {@link RenderingMode} to be used during rendering. If none is specified,
     * the default is {@link RenderingMode#NORMAL}.
     *
     * @param renderingMode the rendering mode to be used
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setRenderingMode(RenderingMode renderingMode) {
        mRenderingMode = renderingMode;
        return this;
    }

    /**
     * Sets the overriding background color to be used, if any. The color should be a
     * bitmask of AARRGGBB. The default is null.
     *
     * @param overrideBgColor the overriding background color to be used in the rendering,
     *            in the form of a AARRGGBB bitmask, or null to use no custom background.
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setOverrideBgColor(Integer overrideBgColor) {
        mOverrideBgColor = overrideBgColor;
        return this;
    }

    /**
     * Sets whether the rendering should include decorations such as a system bar, an
     * application bar etc depending on the SDK target and theme. The default is true.
     *
     * @param showDecorations true if the rendering should include system bars etc.
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setDecorations(boolean showDecorations) {
        mShowDecorations = showDecorations;
        return this;
    }

    /**
     * Sets the nodes to expand during rendering. These will be padded with approximately
     * 20 pixels and also highlighted by the {@link EmptyViewsOverlay}. The default is an
     * empty collection.
     *
     * @param nodesToExpand the nodes to be expanded
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setNodesToExpand(Set<UiElementNode> nodesToExpand) {
        mExpandNodes = nodesToExpand;
        return this;
    }

    /**
     * Sets the {@link Reference} to an outer layout that this layout should be rendered
     * within. The outer layout <b>must</b> contain an include tag which points to this
     * layout. The default is null.
     *
     * @param includedWithin a reference to an outer layout to render this layout within
     * @return this (such that chains of setters can be stringed together)
     */
    public RenderService setIncludedWithin(Reference includedWithin) {
        mIncludedWithin = includedWithin;
        return this;
    }

    /** Initializes any remaining optional fields after all setters have been called */
    private void finishConfiguration() {
        if (mLogger == null) {
            // Silent logging
            mLogger = new LayoutLog();
        }
    }

    /**
     * Renders the model and returns the result as a {@link RenderSession}.
     * @return the {@link RenderSession} resulting from rendering the current model
     */
    public RenderSession createRenderSession() {
        assert mModel != null : "Incomplete service config";
        finishConfiguration();

        if (mResourceResolver == null) {
            // Abort the rendering if the resources are not found.
            return null;
        }

        HardwareConfig hardwareConfig = mHardwareConfigHelper.getConfig();

        UiElementPullParser modelParser = new UiElementPullParser(mModel,
                false, mExpandNodes, hardwareConfig.getDensity(), mProject);
        ILayoutPullParser topParser = modelParser;

        // Code to support editing included layout
        // first reset the layout parser just in case.
        mProjectCallback.setLayoutParser(null, null);

        if (mIncludedWithin != null) {
            // Outer layout name:
            String contextLayoutName = mIncludedWithin.getName();

            // Find the layout file.
            ResourceValue contextLayout = mResourceResolver.findResValue(
                    LAYOUT_RESOURCE_PREFIX + contextLayoutName, false  /* forceFrameworkOnly*/);
            if (contextLayout != null) {
                File layoutFile = new File(contextLayout.getValue());
                if (layoutFile.isFile()) {
                    try {
                        // Get the name of the layout actually being edited, without the extension
                        // as it's what IXmlPullParser.getParser(String) will receive.
                        String queryLayoutName = mEditor.getLayoutResourceName();
                        mProjectCallback.setLayoutParser(queryLayoutName, modelParser);
                        topParser = new ContextPullParser(mProjectCallback, layoutFile);
                        topParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
                        String xmlText = Files.toString(layoutFile, Charsets.UTF_8);
                        topParser.setInput(new StringReader(xmlText));
                    } catch (IOException e) {
                        AdtPlugin.log(e, null);
                    } catch (XmlPullParserException e) {
                        AdtPlugin.log(e, null);
                    }
                }
            }
        }

        SessionParams params = new SessionParams(
                topParser,
                mRenderingMode,
                mProject /* projectKey */,
                hardwareConfig,
                mResourceResolver,
                mProjectCallback,
                mMinSdkVersion,
                mTargetSdkVersion,
                mLogger);

        // Request margin and baseline information.
        // TODO: Be smarter about setting this; start without it, and on the first request
        // for an extended view info, re-render in the same session, and then set a flag
        // which will cause this to create extended view info each time from then on in the
        // same session
        params.setExtendedViewInfoMode(true);

        params.setLocale(mLocale.toLocaleId());
        params.setAssetRepository(new AssetRepository());

        ManifestInfo manifestInfo = ManifestInfo.get(mProject);
        try {
            params.setRtlSupport(manifestInfo.isRtlSupported());
        } catch (Exception e) {
            // ignore.
        }
        if (!mShowDecorations) {
            params.setForceNoDecor();
        } else {
            try {
                params.setAppLabel(manifestInfo.getApplicationLabel());
                params.setAppIcon(manifestInfo.getApplicationIcon());
                String activity = mEditor.getConfigurationChooser().getConfiguration().getActivity();
                if (activity != null) {
                    ActivityAttributes info = manifestInfo.getActivityAttributes(activity);
                    if (info != null) {
                        if (info.getLabel() != null) {
                            params.setAppLabel(info.getLabel());
                        }
                        if (info.getIcon() != null) {
                            params.setAppIcon(info.getIcon());
                        }
                    }
                }
            } catch (Exception e) {
                // ignore.
            }
        }

        if (mOverrideBgColor != null) {
            params.setOverrideBgColor(mOverrideBgColor.intValue());
        }

        // set the Image Overlay as the image factory.
        params.setImageFactory(mImageFactory);

        mProjectCallback.setLogger(mLogger);
        mProjectCallback.setResourceResolver(mResourceResolver);
        RenderSecurityManager securityManager = createSecurityManager();
        try {
            securityManager.setActive(true, mCredential);
            synchronized (RENDERING_LOCK) {
                return mLayoutLib.createSession(params);
            }
        } catch (RuntimeException t) {
            // Exceptions from the bridge
            mLogger.error(null, t.getLocalizedMessage(), t, null);
            throw t;
        } finally {
            securityManager.dispose(mCredential);
            mProjectCallback.setLogger(null);
            mProjectCallback.setResourceResolver(null);
        }
    }

    /**
     * Renders the given resource value (which should refer to a drawable) and returns it
     * as an image
     *
     * @param drawableResourceValue the drawable resource value to be rendered, or null
     * @return the image, or null if something went wrong
     */
    public BufferedImage renderDrawable(ResourceValue drawableResourceValue) {
        if (drawableResourceValue == null) {
            return null;
        }

        finishConfiguration();

        HardwareConfig hardwareConfig = mHardwareConfigHelper.getConfig();

        DrawableParams params = new DrawableParams(drawableResourceValue, mProject, hardwareConfig,
                mResourceResolver, mProjectCallback, mMinSdkVersion,
                mTargetSdkVersion, mLogger);
        params.setAssetRepository(new AssetRepository());
        params.setForceNoDecor();
        Result result = mLayoutLib.renderDrawable(params);
        if (result != null && result.isSuccess()) {
            Object data = result.getData();
            if (data instanceof BufferedImage) {
                return (BufferedImage) data;
            }
        }

        return null;
    }

    /**
     * Measure the children of the given parent node, applying the given filter to the
     * pull parser's attribute values.
     *
     * @param parent the parent node to measure children for
     * @param filter the filter to apply to the attribute values
     * @return a map from node children of the parent to new bounds of the nodes
     */
    public Map<INode, Rect> measureChildren(INode parent,
            final IClientRulesEngine.AttributeFilter filter) {
        finishConfiguration();
        HardwareConfig hardwareConfig = mHardwareConfigHelper.getConfig();

        final NodeFactory mNodeFactory = mEditor.getCanvasControl().getNodeFactory();
        UiElementNode parentNode = ((NodeProxy) parent).getNode();
        UiElementPullParser topParser = new UiElementPullParser(parentNode,
                false, Collections.<UiElementNode>emptySet(), hardwareConfig.getDensity(),
                mProject) {
            @Override
            public String getAttributeValue(String namespace, String localName) {
                if (filter != null) {
                    Object cookie = getViewCookie();
                    if (cookie instanceof UiViewElementNode) {
                        NodeProxy node = mNodeFactory.create((UiViewElementNode) cookie);
                        if (node != null) {
                            String value = filter.getAttribute(node, namespace, localName);
                            if (value != null) {
                                return value;
                            }
                            // null means no preference, not "unset".
                        }
                    }
                }

                return super.getAttributeValue(namespace, localName);
            }

            /**
             * The parser usually assumes that the top level node is a document node that
             * should be skipped, and that's not the case when we render in the middle of
             * the tree, so override {@link UiElementPullParser#onNextFromStartDocument}
             * to change this behavior
             */
            @Override
            public void onNextFromStartDocument() {
                mParsingState = START_TAG;
            }
        };

        SessionParams params = new SessionParams(
                topParser,
                RenderingMode.FULL_EXPAND,
                mProject /* projectKey */,
                hardwareConfig,
                mResourceResolver,
                mProjectCallback,
                mMinSdkVersion,
                mTargetSdkVersion,
                mLogger);
        params.setLayoutOnly();
        params.setForceNoDecor();
        params.setAssetRepository(new AssetRepository());

        RenderSession session = null;
        mProjectCallback.setLogger(mLogger);
        mProjectCallback.setResourceResolver(mResourceResolver);
        RenderSecurityManager securityManager = createSecurityManager();
        try {
            securityManager.setActive(true, mCredential);
            synchronized (RENDERING_LOCK) {
                session = mLayoutLib.createSession(params);
            }
            if (session.getResult().isSuccess()) {
                assert session.getRootViews().size() == 1;
                ViewInfo root = session.getRootViews().get(0);
                List<ViewInfo> children = root.getChildren();
                Map<INode, Rect> map = new HashMap<INode, Rect>(children.size());
                for (ViewInfo info : children) {
                    if (info.getCookie() instanceof UiViewElementNode) {
                        UiViewElementNode uiNode = (UiViewElementNode) info.getCookie();
                        NodeProxy node = mNodeFactory.create(uiNode);
                        map.put(node, new Rect(info.getLeft(), info.getTop(),
                                info.getRight() - info.getLeft(),
                                info.getBottom() - info.getTop()));
                    }
                }

                return map;
            }
        } catch (RuntimeException t) {
            // Exceptions from the bridge
            mLogger.error(null, t.getLocalizedMessage(), t, null);
            throw t;
        } finally {
            securityManager.dispose(mCredential);
            mProjectCallback.setLogger(null);
            mProjectCallback.setResourceResolver(null);
            if (session != null) {
                session.dispose();
            }
        }

        return null;
    }
}
