/*
 * Copyright (C) 2008 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.otherxml.descriptors;

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

import com.android.SdkConstants;
import com.android.ide.common.resources.platform.AttributeInfo;
import com.android.ide.common.resources.platform.DeclareStyleableInfo;
import com.android.ide.common.resources.platform.ViewClassInfo;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DocumentDescriptor;
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.SeparatorAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.XmlnsAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.layout.descriptors.ViewElementDescriptor;

import java.util.ArrayList;
import java.util.Map;


/**
 * Description of the /res/xml structure.
 * Currently supports the <searchable> and <preferences> root nodes.
 */
public final class OtherXmlDescriptors implements IDescriptorProvider {

    // Public attributes names, attributes descriptors and elements descriptors referenced
    // elsewhere.
    public static final String PREF_KEY_ATTR = "key"; //$NON-NLS-1$

    /** The root document descriptor for both searchable and preferences. */
    private DocumentDescriptor mDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$

    /** The root document descriptor for searchable. */
    private DocumentDescriptor mSearchDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$

    /** The root document descriptor for preferences. */
    private DocumentDescriptor mPrefDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$

    /** The root document descriptor for widget provider. */
    private DocumentDescriptor mAppWidgetDescriptor = new DocumentDescriptor("xml_doc", null /* children */); //$NON-NLS-1$

    /** @return the root descriptor for both searchable and preferences. */
    @Override
    public DocumentDescriptor getDescriptor() {
        return mDescriptor;
    }

    @Override
    public ElementDescriptor[] getRootElementDescriptors() {
        return mDescriptor.getChildren();
    }

    /** @return the root descriptor for searchable. */
    public DocumentDescriptor getSearchableDescriptor() {
        return mSearchDescriptor;
    }

    /** @return the root descriptor for preferences. */
    public DocumentDescriptor getPreferencesDescriptor() {
        return mPrefDescriptor;
    }

    /** @return the root descriptor for widget providers. */
    public DocumentDescriptor getAppWidgetDescriptor() {
        return mAppWidgetDescriptor;
    }

    public IDescriptorProvider getSearchableProvider() {
        return new IDescriptorProvider() {
            @Override
            public ElementDescriptor getDescriptor() {
                return mSearchDescriptor;
            }

            @Override
            public ElementDescriptor[] getRootElementDescriptors() {
                return mSearchDescriptor.getChildren();
            }
        };
    }

    public IDescriptorProvider getPreferencesProvider() {
        return new IDescriptorProvider() {
            @Override
            public ElementDescriptor getDescriptor() {
                return mPrefDescriptor;
            }

            @Override
            public ElementDescriptor[] getRootElementDescriptors() {
                return mPrefDescriptor.getChildren();
            }
        };
    }

    public IDescriptorProvider getAppWidgetProvider() {
        return new IDescriptorProvider() {
            @Override
            public ElementDescriptor getDescriptor() {
                return mAppWidgetDescriptor;
            }

            @Override
            public ElementDescriptor[] getRootElementDescriptors() {
                return mAppWidgetDescriptor.getChildren();
            }
        };
    }

    /**
     * Updates the document descriptor.
     * <p/>
     * It first computes the new children of the descriptor and then updates them
     * all at once.
     *
     * @param searchableStyleMap The map style=>attributes for <searchable> from the attrs.xml file
     * @param appWidgetStyleMap The map style=>attributes for <appwidget-provider> from the attrs.xml file
     * @param prefs The list of non-group preference descriptions
     * @param prefGroups The list of preference group descriptions
     */
    public synchronized void updateDescriptors(
            Map<String, DeclareStyleableInfo> searchableStyleMap,
            Map<String, DeclareStyleableInfo> appWidgetStyleMap,
            ViewClassInfo[] prefs, ViewClassInfo[] prefGroups) {

        XmlnsAttributeDescriptor xmlns = new XmlnsAttributeDescriptor(ANDROID_NS_NAME,
                ANDROID_URI);

        ElementDescriptor searchable = createSearchable(searchableStyleMap, xmlns);
        ElementDescriptor appWidget = createAppWidgetProviderInfo(appWidgetStyleMap, xmlns);
        ElementDescriptor preferences = createPreference(prefs, prefGroups, xmlns);
        ArrayList<ElementDescriptor> list =  new ArrayList<ElementDescriptor>();
        if (searchable != null) {
            list.add(searchable);
            mSearchDescriptor.setChildren(new ElementDescriptor[]{ searchable });
        }
        if (appWidget != null) {
            list.add(appWidget);
            mAppWidgetDescriptor.setChildren(new ElementDescriptor[]{ appWidget });
        }
        if (preferences != null) {
            list.add(preferences);
            mPrefDescriptor.setChildren(new ElementDescriptor[]{ preferences });
        }

        if (list.size() > 0) {
            mDescriptor.setChildren(list.toArray(new ElementDescriptor[list.size()]));
        }
    }

    //-------------------------
    // Creation of <searchable>
    //-------------------------

    /**
     * Returns the new ElementDescriptor for <searchable>
     */
    private ElementDescriptor createSearchable(
            Map<String, DeclareStyleableInfo> searchableStyleMap,
            XmlnsAttributeDescriptor xmlns) {

        ElementDescriptor action_key = createElement(searchableStyleMap,
                "SearchableActionKey", //$NON-NLS-1$ styleName
                "actionkey", //$NON-NLS-1$ xmlName
                "Action Key", // uiName
                null, // sdk url
                null, // extraAttribute
                null, // childrenElements
                false /* mandatory */ );

        ElementDescriptor searchable = createElement(searchableStyleMap,
                "Searchable", //$NON-NLS-1$ styleName
                "searchable", //$NON-NLS-1$ xmlName
                "Searchable", // uiName
                null, // sdk url
                xmlns, // extraAttribute
                new ElementDescriptor[] { action_key }, // childrenElements
                false /* mandatory */ );
        return searchable;
    }

    /**
     * Returns the new ElementDescriptor for <appwidget-provider>
     */
    private ElementDescriptor createAppWidgetProviderInfo(
            Map<String, DeclareStyleableInfo> appWidgetStyleMap,
            XmlnsAttributeDescriptor xmlns) {

        if (appWidgetStyleMap == null) {
            return null;
        }

        ElementDescriptor appWidget = createElement(appWidgetStyleMap,
                "AppWidgetProviderInfo", //$NON-NLS-1$ styleName
                "appwidget-provider", //$NON-NLS-1$ xmlName
                "AppWidget Provider", // uiName
                null, // sdk url
                xmlns, // extraAttribute
                null, // childrenElements
                false /* mandatory */ );
        return appWidget;
    }

    /**
     * Returns a new ElementDescriptor constructed from the information given here
     * and the javadoc & attributes extracted from the style map if any.
     */
    private ElementDescriptor createElement(
            Map<String, DeclareStyleableInfo> styleMap, String styleName,
            String xmlName, String uiName, String sdkUrl,
            AttributeDescriptor extraAttribute,
            ElementDescriptor[] childrenElements, boolean mandatory) {

        ElementDescriptor element = new ElementDescriptor(xmlName, uiName, null, sdkUrl,
                null, childrenElements, mandatory);

        return updateElement(element, styleMap, styleName, extraAttribute);
    }

    /**
     * Updates an ElementDescriptor with the javadoc & attributes extracted from the style
     * map if any.
     */
    private ElementDescriptor updateElement(ElementDescriptor element,
            Map<String, DeclareStyleableInfo> styleMap,
            String styleName,
            AttributeDescriptor extraAttribute) {
        ArrayList<AttributeDescriptor> descs = new ArrayList<AttributeDescriptor>();

        DeclareStyleableInfo style = styleMap != null ? styleMap.get(styleName) : null;
        if (style != null) {
            DescriptorsUtils.appendAttributes(descs,
                    null,   // elementName
                    SdkConstants.NS_RESOURCES,
                    style.getAttributes(),
                    null,   // requiredAttributes
                    null);  // overrides
            element.setTooltip(style.getJavaDoc());
        }

        if (extraAttribute != null) {
            descs.add(extraAttribute);
        }

        element.setAttributes(descs.toArray(new AttributeDescriptor[descs.size()]));
        return element;
    }

    //--------------------------
    // Creation of <Preferences>
    //--------------------------

    /**
     * Returns the new ElementDescriptor for <Preferences>
     */
    private ElementDescriptor createPreference(ViewClassInfo[] prefs,
            ViewClassInfo[] prefGroups, XmlnsAttributeDescriptor xmlns) {

        ArrayList<ElementDescriptor> newPrefs = new ArrayList<ElementDescriptor>();
        if (prefs != null) {
            for (ViewClassInfo info : prefs) {
                ElementDescriptor desc = convertPref(info);
                newPrefs.add(desc);
            }
        }

        ElementDescriptor topPreferences = null;

        ArrayList<ElementDescriptor> newGroups = new ArrayList<ElementDescriptor>();
        if (prefGroups != null) {
            for (ViewClassInfo info : prefGroups) {
                ElementDescriptor desc = convertPref(info);
                newGroups.add(desc);

                if (info.getFullClassName() == SdkConstants.CLASS_PREFERENCES) {
                    topPreferences = desc;
                }
            }
        }

        ArrayList<ElementDescriptor> everything = new ArrayList<ElementDescriptor>();
        everything.addAll(newGroups);
        everything.addAll(newPrefs);
        ElementDescriptor[] newArray = everything.toArray(new ElementDescriptor[everything.size()]);

        // Link all groups to everything else here.. recursively
        for (ElementDescriptor layoutDesc : newGroups) {
            layoutDesc.setChildren(newArray);
        }

        // The "top" element to be returned corresponds to the class "Preferences".
        // Its descriptor has already been created. However the root one also needs
        // the hidden xmlns:android definition..
        if (topPreferences != null) {
            AttributeDescriptor[] attrs = topPreferences.getAttributes();
            AttributeDescriptor[] newAttrs = new AttributeDescriptor[attrs.length + 1];
            System.arraycopy(attrs, 0, newAttrs, 0, attrs.length);
            newAttrs[attrs.length] = xmlns;
            return new ElementDescriptor(
                    topPreferences.getXmlName(),
                    topPreferences.getUiName(),
                    topPreferences.getTooltip(),
                    topPreferences.getSdkUrl(),
                    newAttrs,
                    topPreferences.getChildren(),
                    false /* mandatory */);
        } else {
            return null;
        }
    }

    /**
     * Creates an element descriptor from a given {@link ViewClassInfo}.
     */
    private ElementDescriptor convertPref(ViewClassInfo info) {
        String xml_name = info.getShortClassName();
        String tooltip = info.getJavaDoc();

        // Process all Preference attributes
        ArrayList<AttributeDescriptor> attributes = new ArrayList<AttributeDescriptor>();
        DescriptorsUtils.appendAttributes(attributes,
                null,   // elementName
                SdkConstants.NS_RESOURCES,
                info.getAttributes(),
                null,   // requiredAttributes
                null);  // overrides

        for (ViewClassInfo link = info.getSuperClass();
                link != null;
                link = link.getSuperClass()) {
            AttributeInfo[] attrList = link.getAttributes();
            if (attrList.length > 0) {
                attributes.add(new SeparatorAttributeDescriptor(
                        String.format("Attributes from %1$s", link.getShortClassName())));
                DescriptorsUtils.appendAttributes(attributes,
                        null,   // elementName
                        SdkConstants.NS_RESOURCES,
                        attrList,
                        null,   // requiredAttributes
                        null);  // overrides
            }
        }

        return new ViewElementDescriptor(xml_name,
                xml_name, // ui_name
                info.getFullClassName(),
                tooltip,
                null, // sdk_url
                attributes.toArray(new AttributeDescriptor[attributes.size()]),
                null,
                null, // children
                false /* mandatory */);
    }
}
