/*
 * Copyright (C) 2007 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.uimodel;

import static com.android.SdkConstants.ANDROID_PKG;
import static com.android.SdkConstants.ANDROID_PREFIX;
import static com.android.SdkConstants.ANDROID_THEME_PREFIX;
import static com.android.SdkConstants.ATTR_ID;
import static com.android.SdkConstants.ATTR_LAYOUT;
import static com.android.SdkConstants.ATTR_STYLE;
import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
import static com.android.SdkConstants.PREFIX_THEME_REF;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.ide.common.api.IAttributeInfo;
import com.android.ide.common.api.IAttributeInfo.Format;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
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.TextAttributeDescriptor;
import com.android.ide.eclipse.adt.internal.editors.ui.SectionHelper;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
import com.android.ide.eclipse.adt.internal.ui.ReferenceChooserDialog;
import com.android.ide.eclipse.adt.internal.ui.ResourceChooser;
import com.android.resources.ResourceType;

import org.eclipse.core.resources.IProject;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Represents an XML attribute for a resource that can be modified using a simple text field or
 * a dialog to choose an existing resource.
 * <p/>
 * It can be configured to represent any kind of resource, by providing the desired
 * {@link ResourceType} in the constructor.
 * <p/>
 * See {@link UiTextAttributeNode} for more information.
 */
public class UiResourceAttributeNode extends UiTextAttributeNode {
    private ResourceType mType;

    /**
     * Creates a new {@linkplain UiResourceAttributeNode}
     *
     * @param type the associated resource type
     * @param attributeDescriptor the attribute descriptor for this attribute
     * @param uiParent the parent ui node, if any
     */
    public UiResourceAttributeNode(ResourceType type,
            AttributeDescriptor attributeDescriptor, UiElementNode uiParent) {
        super(attributeDescriptor, uiParent);

        mType = type;
    }

    /* (non-java doc)
     * Creates a label widget and an associated text field.
     * <p/>
     * As most other parts of the android manifest editor, this assumes the
     * parent uses a table layout with 2 columns.
     */
    @Override
    public void createUiControl(final Composite parent, IManagedForm managedForm) {
        setManagedForm(managedForm);
        FormToolkit toolkit = managedForm.getToolkit();
        TextAttributeDescriptor desc = (TextAttributeDescriptor) getDescriptor();

        Label label = toolkit.createLabel(parent, desc.getUiName());
        label.setLayoutData(new TableWrapData(TableWrapData.LEFT, TableWrapData.MIDDLE));
        SectionHelper.addControlTooltip(label, DescriptorsUtils.formatTooltip(desc.getTooltip()));

        Composite composite = toolkit.createComposite(parent);
        composite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE));
        GridLayout gl = new GridLayout(2, false);
        gl.marginHeight = gl.marginWidth = 0;
        composite.setLayout(gl);
        // Fixes missing text borders under GTK... also requires adding a 1-pixel margin
        // for the text field below
        toolkit.paintBordersFor(composite);

        final Text text = toolkit.createText(composite, getCurrentValue());
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalIndent = 1;  // Needed by the fixed composite borders under GTK
        text.setLayoutData(gd);
        Button browseButton = toolkit.createButton(composite, "Browse...", SWT.PUSH);

        setTextWidget(text);

        // TODO Add a validator using onAddModifyListener

        browseButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                String result = showDialog(parent.getShell(), text.getText().trim());
                if (result != null) {
                    text.setText(result);
                }
            }
        });
    }

    /**
     * Shows a dialog letting the user choose a set of enum, and returns a
     * string containing the result.
     *
     * @param shell the parent shell
     * @param currentValue an initial value, if any
     * @return the chosen string, or null
     */
    @Nullable
    public String showDialog(@NonNull Shell shell, @Nullable String currentValue) {
        // we need to get the project of the file being edited.
        UiElementNode uiNode = getUiParent();
        AndroidXmlEditor editor = uiNode.getEditor();
        IProject project = editor.getProject();
        if (project != null) {
            // get the resource repository for this project and the system resources.
            ResourceRepository projectRepository =
                ResourceManager.getInstance().getProjectResources(project);

            if (mType != null) {
                // get the Target Data to get the system resources
                AndroidTargetData data = editor.getTargetData();
                ResourceChooser dlg = ResourceChooser.create(project, mType, data, shell)
                    .setCurrentResource(currentValue);
                if (dlg.open() == Window.OK) {
                    return dlg.getCurrentResource();
                }
            } else {
                ReferenceChooserDialog dlg = new ReferenceChooserDialog(
                        project,
                        projectRepository,
                        shell);

                dlg.setCurrentResource(currentValue);

                if (dlg.open() == Window.OK) {
                    return dlg.getCurrentResource();
                }
            }
        }

        return null;
    }

    /**
     * Gets all the values one could use to auto-complete a "resource" value in an XML
     * content assist.
     * <p/>
     * Typically the user is editing the value of an attribute in a resource XML, e.g.
     *   <pre> "&lt;Button android:test="@string/my_[caret]_string..." </pre>
     * <p/>
     *
     * "prefix" is the value that the user has typed so far (or more exactly whatever is on the
     * left side of the insertion point). In the example above it would be "@style/my_".
     * <p/>
     *
     * To avoid a huge long list of values, the completion works on two levels:
     * <ul>
     * <li> If a resource type as been typed so far (e.g. "@style/"), then limit the values to
     *      the possible completions that match this type.
     * <li> If no resource type as been typed so far, then return the various types that could be
     *      completed. So if the project has only strings and layouts resources, for example,
     *      the returned list will only include "@string/" and "@layout/".
     * </ul>
     *
     * Finally if anywhere in the string we find the special token "android:", we use the
     * current framework system resources rather than the project resources.
     * This works for both "@android:style/foo" and "@style/android:foo" conventions even though
     * the reconstructed name will always be of the former form.
     *
     * Note that "android:" here is a keyword specific to Android resources and should not be
     * mixed with an XML namespace for an XML attribute name.
     */
    @Override
    public String[] getPossibleValues(String prefix) {
        return computeResourceStringMatches(getUiParent().getEditor(), getDescriptor(), prefix);
    }

    /**
     * Computes the set of resource string matches for a given resource prefix in a given editor
     *
     * @param editor the editor context
     * @param descriptor the attribute descriptor, if any
     * @param prefix the prefix, if any
     * @return an array of resource string matches
     */
    @Nullable
    public static String[] computeResourceStringMatches(
            @NonNull AndroidXmlEditor editor,
            @Nullable AttributeDescriptor descriptor,
            @Nullable String prefix) {

        if (prefix == null || !prefix.regionMatches(1, ANDROID_PKG, 0, ANDROID_PKG.length())) {
            IProject project = editor.getProject();
            if (project != null) {
                // get the resource repository for this project and the system resources.
                ResourceManager resourceManager = ResourceManager.getInstance();
                ResourceRepository repository = resourceManager.getProjectResources(project);

                List<IProject> libraries = null;
                ProjectState projectState = Sdk.getProjectState(project);
                if (projectState != null) {
                    libraries = projectState.getFullLibraryProjects();
                }

                String[] projectMatches = computeResourceStringMatches(descriptor, prefix,
                        repository, false);

                if (libraries == null || libraries.isEmpty()) {
                    return projectMatches;
                }

                // Also compute matches for each of the libraries, and combine them
                Set<String> matches = new HashSet<String>(200);
                for (String s : projectMatches) {
                    matches.add(s);
                }

                for (IProject library : libraries) {
                    repository = resourceManager.getProjectResources(library);
                    projectMatches = computeResourceStringMatches(descriptor, prefix,
                            repository, false);
                    for (String s : projectMatches) {
                        matches.add(s);
                    }
                }

                String[] sorted = matches.toArray(new String[matches.size()]);
                Arrays.sort(sorted);
                return sorted;
            }
        } else {
            // If there's a prefix with "android:" in it, use the system resources
            // Non-public framework resources are filtered out later.
            AndroidTargetData data = editor.getTargetData();
            if (data != null) {
                ResourceRepository repository = data.getFrameworkResources();
                return computeResourceStringMatches(descriptor, prefix, repository, true);
            }
        }

        return null;
    }

    /**
     * Computes the set of resource string matches for a given prefix and a
     * given resource repository
     *
     * @param attributeDescriptor the attribute descriptor, if any
     * @param prefix the prefix, if any
     * @param repository the repository to seaerch in
     * @param isSystem if true, the repository contains framework repository,
     *            otherwise it contains project repositories
     * @return an array of resource string matches
     */
    @NonNull
    public static String[] computeResourceStringMatches(
            @Nullable AttributeDescriptor attributeDescriptor,
            @Nullable String prefix,
            @NonNull ResourceRepository repository,
            boolean isSystem) {
        // Get list of potential resource types, either specific to this project
        // or the generic list.
        Collection<ResourceType> resTypes = (repository != null) ?
                    repository.getAvailableResourceTypes() :
                    EnumSet.allOf(ResourceType.class);

        // Get the type name from the prefix, if any. It's any word before the / if there's one
        String typeName = null;
        if (prefix != null) {
            Matcher m = Pattern.compile(".*?([a-z]+)/.*").matcher(prefix);      //$NON-NLS-1$
            if (m.matches()) {
                typeName = m.group(1);
            }
        }

        // Now collect results
        List<String> results = new ArrayList<String>();

        if (typeName == null) {
            // This prefix does not have a / in it, so the resource string is either empty
            // or does not have the resource type in it. Simply offer the list of potential
            // resource types.
            if (prefix != null && prefix.startsWith(PREFIX_THEME_REF)) {
                results.add(ANDROID_THEME_PREFIX + ResourceType.ATTR.getName() + '/');
                if (resTypes.contains(ResourceType.ATTR)
                        || resTypes.contains(ResourceType.STYLE)) {
                    results.add(PREFIX_THEME_REF + ResourceType.ATTR.getName() + '/');
                    if (prefix != null && prefix.startsWith(ANDROID_THEME_PREFIX)) {
                        // including attr isn't required
                        for (ResourceItem item : repository.getResourceItemsOfType(
                                ResourceType.ATTR)) {
                            results.add(ANDROID_THEME_PREFIX + item.getName());
                        }
                    }
                }
                return results.toArray(new String[results.size()]);
            }

            for (ResourceType resType : resTypes) {
                if (isSystem) {
                    results.add(ANDROID_PREFIX + resType.getName() + '/');
                } else {
                    results.add('@' + resType.getName() + '/');
                }
                if (resType == ResourceType.ID) {
                    // Also offer the + version to create an id from scratch
                    results.add("@+" + resType.getName() + '/');    //$NON-NLS-1$
                }
            }

            // Also add in @android: prefix to completion such that if user has typed
            // "@an" we offer to complete it.
            if (prefix == null ||
                    ANDROID_PKG.regionMatches(0, prefix, 1, prefix.length() - 1)) {
                results.add(ANDROID_PREFIX);
            }
        } else if (repository != null) {
            // We have a style name and a repository. Find all resources that match this
            // type and recreate suggestions out of them.

            String initial = prefix != null && prefix.startsWith(PREFIX_THEME_REF)
                    ? PREFIX_THEME_REF : PREFIX_RESOURCE_REF;
            ResourceType resType = ResourceType.getEnum(typeName);
            if (resType != null) {
                StringBuilder sb = new StringBuilder();
                sb.append(initial);
                if (prefix != null && prefix.indexOf('+') >= 0) {
                    sb.append('+');
                }

                if (isSystem) {
                    sb.append(ANDROID_PKG).append(':');
                }

                sb.append(typeName).append('/');
                String base = sb.toString();

                for (ResourceItem item : repository.getResourceItemsOfType(resType)) {
                    results.add(base + item.getName());
                }

                if (!isSystem && resType == ResourceType.ATTR) {
                    for (ResourceItem item : repository.getResourceItemsOfType(
                            ResourceType.STYLE)) {
                        results.add(base + item.getName());
                    }
                }
            }
        }

        if (attributeDescriptor != null) {
            sortAttributeChoices(attributeDescriptor, results);
        } else {
            Collections.sort(results);
        }

        return results.toArray(new String[results.size()]);
    }

    /**
     * Attempts to sort the attribute values to bubble up the most likely choices to
     * the top.
     * <p>
     * For example, if you are editing a style attribute, it's likely that among the
     * resource values you would rather see @style or @android than @string.
     * @param descriptor the descriptor that the resource values are being completed for,
     *          used to prioritize some of the resource types
     * @param choices the set of string resource values
     */
    public static void sortAttributeChoices(AttributeDescriptor descriptor,
            List<String> choices) {
        final IAttributeInfo attributeInfo = descriptor.getAttributeInfo();
        Collections.sort(choices, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int compare = score(attributeInfo, s1) - score(attributeInfo, s2);
                if (compare == 0) {
                    // Sort alphabetically as a fallback
                    compare = s1.compareToIgnoreCase(s2);
                }
                return compare;
            }
        });
    }

    /** Compute a suitable sorting score for the given  */
    private static final int score(IAttributeInfo attributeInfo, String value) {
        if (value.equals(ANDROID_PREFIX)) {
            return -1;
        }

        for (Format format : attributeInfo.getFormats()) {
            String type = null;
            switch (format) {
                case BOOLEAN:
                    type = "bool"; //$NON-NLS-1$
                    break;
                case COLOR:
                    type = "color"; //$NON-NLS-1$
                    break;
                case DIMENSION:
                    type = "dimen"; //$NON-NLS-1$
                    break;
                case INTEGER:
                    type = "integer"; //$NON-NLS-1$
                    break;
                case STRING:
                    type = "string"; //$NON-NLS-1$
                    break;
                // default: REFERENCE, FLAG, ENUM, etc - don't have type info about individual
                // elements to help make a decision
            }

            if (type != null) {
                if (value.startsWith(PREFIX_RESOURCE_REF)) {
                    if (value.startsWith(PREFIX_RESOURCE_REF + type + '/')) {
                        return -2;
                    }

                    if (value.startsWith(ANDROID_PREFIX + type + '/')) {
                        return -2;
                    }
                }
                if (value.startsWith(PREFIX_THEME_REF)) {
                    if (value.startsWith(PREFIX_THEME_REF + type + '/')) {
                        return -2;
                    }

                    if (value.startsWith(ANDROID_THEME_PREFIX + type + '/')) {
                        return -2;
                    }
                }
            }
        }

        // Handle a few more cases not covered by the Format metadata check
        String type = null;

        String attribute = attributeInfo.getName();
        if (attribute.equals(ATTR_ID)) {
            type = "id"; //$NON-NLS-1$
        } else if (attribute.equals(ATTR_STYLE)) {
            type = "style"; //$NON-NLS-1$
        } else if (attribute.equals(ATTR_LAYOUT)) {
            type = "layout"; //$NON-NLS-1$
        } else if (attribute.equals("drawable")) { //$NON-NLS-1$
            type = "drawable"; //$NON-NLS-1$
        } else if (attribute.equals("entries")) { //$NON-NLS-1$
            // Spinner
            type = "array";    //$NON-NLS-1$
        }

        if (type != null) {
            if (value.startsWith(PREFIX_RESOURCE_REF)) {
                if (value.startsWith(PREFIX_RESOURCE_REF + type + '/')) {
                    return -2;
                }

                if (value.startsWith(ANDROID_PREFIX + type + '/')) {
                    return -2;
                }
            }
            if (value.startsWith(PREFIX_THEME_REF)) {
                if (value.startsWith(PREFIX_THEME_REF + type + '/')) {
                    return -2;
                }

                if (value.startsWith(ANDROID_THEME_PREFIX + type + '/')) {
                    return -2;
                }
            }
        }

        return 0;
    }
}
