/*
 * 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 com.android.SdkConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
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.ListAttributeDescriptor;
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.sdk.AndroidTargetData;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.TableWrapData;

/**
 * Represents an XML attribute which has possible built-in values, and can be modified by
 * an editable Combo box.
 * <p/>
 * See {@link UiTextAttributeNode} for more information.
 */
public class UiListAttributeNode extends UiAbstractTextAttributeNode {

    protected Combo mCombo;

    public UiListAttributeNode(ListAttributeDescriptor attributeDescriptor,
            UiElementNode uiParent) {
        super(attributeDescriptor, uiParent);
    }

    /* (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 final void createUiControl(final Composite parent, IManagedForm 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()));

        int style = SWT.DROP_DOWN;
        mCombo = new Combo(parent, style);
        TableWrapData twd = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.MIDDLE);
        twd.maxWidth = 100;
        mCombo.setLayoutData(twd);

        fillCombo();

        setTextWidgetValue(getCurrentValue());

        mCombo.addModifyListener(new ModifyListener() {
            /**
             * Sent when the text is modified, whether by the user via manual
             * input or programmatic input via setText().
             */
            @Override
            public void modifyText(ModifyEvent e) {
                onComboChange();
            }
        });

        mCombo.addSelectionListener(new SelectionAdapter() {
            /** Sent when the text is changed from a list selection. */
            @Override
            public void widgetSelected(SelectionEvent e) {
                onComboChange();
            }
        });

        // Remove self-reference when the widget is disposed
        mCombo.addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(DisposeEvent e) {
                mCombo = null;
            }
        });
    }

    protected void fillCombo() {
        String[] values = getPossibleValues(null);

        if (values == null) {
            AdtPlugin.log(IStatus.ERROR,
                    "FrameworkResourceManager did not provide values yet for %1$s",
                    getDescriptor().getXmlLocalName());
        } else {
            for (String value : values) {
                mCombo.add(value);
            }
        }
    }

    /**
     * Get the list values, either from the initial values set in the attribute
     * or by querying the framework resource parser.
     *
     * {@inheritDoc}
     */
    @Override
    public String[] getPossibleValues(String prefix) {
        AttributeDescriptor descriptor = getDescriptor();
        UiElementNode uiParent = getUiParent();

        String attr_name = descriptor.getXmlLocalName();
        String element_name = uiParent.getDescriptor().getXmlName();

        // FrameworkResourceManager expects a specific prefix for the attribute.
        String nsPrefix = "";
        if (SdkConstants.NS_RESOURCES.equals(descriptor.getNamespaceUri())) {
            nsPrefix = SdkConstants.ANDROID_NS_NAME + ':';
        } else if (SdkConstants.XMLNS_URI.equals(descriptor.getNamespaceUri())) {
            nsPrefix = SdkConstants.XMLNS_PREFIX;
        }
        attr_name = nsPrefix + attr_name;

        String[] values = null;

        if (descriptor instanceof ListAttributeDescriptor &&
                ((ListAttributeDescriptor) descriptor).getValues() != null) {
            // Get enum values from the descriptor
            values = ((ListAttributeDescriptor) descriptor).getValues();
        }

        if (values == null) {
            // or from the AndroidTargetData
            UiElementNode uiNode = getUiParent();
            AndroidXmlEditor editor = uiNode.getEditor();
            AndroidTargetData data = editor.getTargetData();
            if (data != null) {
                // get the great-grand-parent descriptor.

                // the parent should always exist.
                UiElementNode grandParentNode = uiParent.getUiParent();

                String greatGrandParentNodeName = null;
                if (grandParentNode != null) {
                    UiElementNode greatGrandParentNode = grandParentNode.getUiParent();
                    if (greatGrandParentNode != null) {
                        greatGrandParentNodeName =
                            greatGrandParentNode.getDescriptor().getXmlName();
                    }
                }

                values = data.getAttributeValues(element_name, attr_name, greatGrandParentNodeName);
            }
        }

        return values;
    }

    @Override
    public String getTextWidgetValue() {
        if (mCombo != null) {
            return mCombo.getText();
        }

        return null;
    }

    @Override
    public final boolean isValid() {
        return mCombo != null;
    }

    @Override
    public void setTextWidgetValue(String value) {
        if (mCombo != null) {
            mCombo.setText(value);
        }
    }

    /**
     * Handles Combo change, either from text edit or from selection change.
     * <p/>
     * Simply mark the attribute as dirty if it really changed.
     * The container SectionPart will collect these flag and manage them.
     */
    private void onComboChange() {
        if (!isInInternalTextModification() &&
                !isDirty() &&
                mCombo != null &&
                getCurrentValue() != null &&
                !mCombo.getText().equals(getCurrentValue())) {
            setDirty(true);
        }
    }
}
