/*
 * 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.drawable;

import static com.android.SdkConstants.ANDROID_NS_NAME;
import static com.android.SdkConstants.ANDROID_URI;

import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.eclipse.adt.internal.editors.animator.AnimatorDescriptors;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ElementDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.IDescriptorProvider;
import com.android.ide.eclipse.adt.internal.editors.descriptors.ReferenceAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.resources.ResourceType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Descriptors for /res/drawable files
 */
public class DrawableDescriptors implements IDescriptorProvider {
    private static final String SDK_URL_BASE =
        "http://d.android.com/guide/topics/resources/"; //$NON-NLS-1$

    /** The root element descriptor */
    private ElementDescriptor mDescriptor;
    /** The root element descriptors */
    private ElementDescriptor[] mRootDescriptors;
    private Map<String, ElementDescriptor> nameToDescriptor;

    /** @return the root descriptor. */
    @Override
    public ElementDescriptor getDescriptor() {
        if (mDescriptor == null) {
            mDescriptor = new ElementDescriptor("", getRootElementDescriptors()); //$NON-NLS-1$
        }

        return mDescriptor;
    }

    @Override
    public ElementDescriptor[] getRootElementDescriptors() {
        return mRootDescriptors;
    }

    /**
     * Returns a descriptor for the given root tag name
     *
     * @param tag the tag name to look up a descriptor for
     * @return a descriptor with the given tag name
     */
    public ElementDescriptor getElementDescriptor(String tag) {
        if (nameToDescriptor == null) {
            nameToDescriptor = new HashMap<String, ElementDescriptor>();
            for (ElementDescriptor descriptor : getRootElementDescriptors()) {
                nameToDescriptor.put(descriptor.getXmlName(), descriptor);
            }
        }

        ElementDescriptor descriptor = nameToDescriptor.get(tag);
        if (descriptor == null) {
            descriptor = getDescriptor();
        }
        return descriptor;
    }

    public synchronized void updateDescriptors(Map<String, DeclareStyleableInfo> styleMap) {
        XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
                ANDROID_URI);
        List<ElementDescriptor> descriptors = new ArrayList<ElementDescriptor>();

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "animation-list", "Animation List", "AnimationDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An animation defined in XML that shows a sequence of images in "
                + "order (like a film)",
            SDK_URL_BASE + "animation-resource.html#Frame",
            xmlns, null, true /*mandatory*/);

        /* For some reason, android.graphics.drawable.AnimatedRotateDrawable is marked with @hide
         * so we should not register it and its attributes here. See issue #19248 for details.
        AnimatorDescriptors.addElement(descriptors, styleMap,
            "animated-rotate", "Animated Rotate", "AnimatedRotateDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            // Need docs
            null, // tooltip
            null, // sdk_url
            xmlns, null, true);
        */

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "bitmap", "BitMap", "BitmapDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML bitmap is a resource defined in XML that points to a bitmap file. "
                    + "The effect is an alias for a raw bitmap file. The XML can "
                    + "specify additional properties for the bitmap such as "
                    + "dithering and tiling.",
            SDK_URL_BASE + "drawable-resource.html#Bitmap", //$NON-NLS-1$
            xmlns, null, true /* mandatory */);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "clip", "Clip", "ClipDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that defines a drawable that clips another Drawable based on "
                + "this Drawable's current level value.",
            SDK_URL_BASE + "drawable-resource.html#Clip", //$NON-NLS-1$
            xmlns, null, true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "color", "Color", "ColorDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "XML resource that carries a color value (a hexadecimal color)",
            SDK_URL_BASE + "more-resources.html#Color",
            xmlns, null, true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "inset", "Inset", "InsetDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that defines a drawable that insets another drawable by a "
                + "specified distance. This is useful when a View needs a background "
                + "drawble that is smaller than the View's actual bounds.",
            SDK_URL_BASE + "drawable-resource.html#Inset", //$NON-NLS-1$
            xmlns, null, true /*mandatory*/);

        // Layer list

        // An <item> in a <selector> or <
        ElementDescriptor layerItem = AnimatorDescriptors.addElement(null, styleMap,
                "item", "Item", "LayerDrawableItem", null, //$NON-NLS-1$ //$NON-NLS-3$
                "Defines a drawable to place in the layer drawable, in a position "
                    + "defined by its attributes. Must be a child of a <selector> "
                    + "element. Accepts child <bitmap> elements.",
                SDK_URL_BASE + "drawable-resource.html#LayerList", //$NON-NLS-1$
                null, /* extra attribute */
                null, /* This is wrong -- we can now embed any above drawable
                            (but without xmlns as extra) */
                false /*mandatory*/);
        ElementDescriptor[] layerChildren = layerItem != null
            ? new ElementDescriptor[] { layerItem } : null;

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "layer-list", "Layer List", "LayerDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "A Drawable that manages an array of other Drawables. These are drawn in "
                    + "array order, so the element with the largest index is be drawn on top.",
            SDK_URL_BASE + "drawable-resource.html#LayerList", //$NON-NLS-1$
            xmlns,
            layerChildren,
            true /*mandatory*/);

        // Level list children
        ElementDescriptor levelListItem = AnimatorDescriptors.addElement(null, styleMap,
            "item", "Item", "LevelListDrawableItem", null, //$NON-NLS-1$ //$NON-NLS-3$
            "Defines a drawable to use at a certain level.",
            SDK_URL_BASE + "drawable-resource.html#LevelList", //$NON-NLS-1$
            null, /* extra attribute */
            null, /* no further children */
            // TODO: The inflation code seems to show that all drawables can be nested here!
            false /*mandatory*/);
        AnimatorDescriptors.addElement(descriptors, styleMap,
            "level-list", "Level List", "LevelListDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that defines a drawable that manages a number of alternate "
                + "Drawables, each assigned a maximum numerical value",
            SDK_URL_BASE + "drawable-resource.html#LevelList", //$NON-NLS-1$
            xmlns,
            levelListItem != null ? new ElementDescriptor[] { levelListItem } : null,
            true /*mandatory*/);

        // Not yet supported
        //addElement(descriptors, styleMap, "mipmap", "Mipmap", "MipmapDrawable", null,
        //        null /* tooltip */,
        //        null /* sdk_url */,
        //        xmlns, null, true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "nine-patch", "Nine Patch", "NinePatchDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "A PNG file with stretchable regions to allow image resizing "
                    + "based on content (.9.png).",
            SDK_URL_BASE + "drawable-resource.html#NinePatch", //$NON-NLS-1$
            xmlns, null, true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "rotate", "Rotate", "RotateDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            // Need docs
            null /* tooltip */,
            null /* sdk_url */,
            xmlns, null, true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "scale", "Shape", "ScaleDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that defines a drawable that changes the size of another Drawable "
                + "based on its current level value.",
            SDK_URL_BASE + "drawable-resource.html#Scale", //$NON-NLS-1$
            xmlns, null, true /*mandatory*/);

        // Selector children
        ElementDescriptor selectorItem = AnimatorDescriptors.addElement(null, styleMap,
            "item", "Item", "DrawableStates", null, //$NON-NLS-1$ //$NON-NLS-3$
            "Defines a drawable to use during certain states, as described by "
                 + "its attributes. Must be a child of a <selector> element.",
            SDK_URL_BASE + "drawable-resource.html#StateList", //$NON-NLS-1$
            new ReferenceAttributeDescriptor(
                    ResourceType.DRAWABLE, "drawable", ANDROID_URI, //$NON-NLS-1$
                    new AttributeInfo("drawable", Format.REFERENCE_SET))
                    .setTooltip("Reference to a drawable resource."),
            null, /* This is wrong -- we can now embed any above drawable
                        (but without xmlns as extra) */
            false /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "selector", "Selector", "StateListDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that references different bitmap graphics for different states "
                + "(for example, to use a different image when a button is pressed).",
            SDK_URL_BASE + "drawable-resource.html#StateList", //$NON-NLS-1$
            xmlns,
            selectorItem != null ? new ElementDescriptor[] { selectorItem } : null,
            true /*mandatory*/);

        // Shape
        // Shape children
        List<ElementDescriptor> shapeChildren = new ArrayList<ElementDescriptor>();
        // Selector children
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "size", "Size", "GradientDrawableSize", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "gradient", "Gradient", "GradientDrawableGradient", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "solid", "Solid", "GradientDrawableSolid", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "stroke", "Stroke", "GradientDrawableStroke", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "corners", "Corners", "DrawableCorners", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);
        AnimatorDescriptors.addElement(shapeChildren, styleMap,
            "padding", "Padding", "GradientDrawablePadding", null, //$NON-NLS-1$ //$NON-NLS-3$
            null /* tooltip */, null /* sdk_url */, null /* extra attribute */,
            null /* children */, false /* mandatory */);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "shape", "Shape", //$NON-NLS-1$

            // The documentation says that a <shape> element creates a ShapeDrawable,
            // but ShapeDrawable isn't finished and the code currently creates
            // a GradientDrawable.
            //"ShapeDrawable", //$NON-NLS-1$
            "GradientDrawable", //$NON-NLS-1$

            null,
            "An XML file that defines a geometric shape, including colors and gradients.",
            SDK_URL_BASE + "drawable-resource.html#Shape", //$NON-NLS-1$
            xmlns,

            // These are the GradientDrawable children, not the ShapeDrawable children
            shapeChildren.toArray(new ElementDescriptor[shapeChildren.size()]),
            true /*mandatory*/);

        AnimatorDescriptors.addElement(descriptors, styleMap,
            "transition", "Transition", "TransitionDrawable", null, //$NON-NLS-1$ //$NON-NLS-3$
            "An XML file that defines a drawable that can cross-fade between two "
                + "drawable resources. Each drawable is represented by an <item> "
                + "element inside a single <transition> element. No more than two "
                + "items are supported. To transition forward, call startTransition(). "
                + "To transition backward, call reverseTransition().",
            SDK_URL_BASE + "drawable-resource.html#Transition", //$NON-NLS-1$
            xmlns,
            layerChildren, // children: a TransitionDrawable is a LayerDrawable
            true /*mandatory*/);

        mRootDescriptors = descriptors.toArray(new ElementDescriptor[descriptors.size()]);

        // A <selector><item> can contain any of the top level drawables
        if (selectorItem != null) {
            selectorItem.setChildren(mRootDescriptors);
        }
        // Docs says it can accept <bitmap> but code comment suggests any is possible;
        // test and either use this or just { bitmap }
        if (layerItem != null) {
            layerItem.setChildren(mRootDescriptors);
        }
    }
}
