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

import static com.android.SdkConstants.ATTR_TEXT_SIZE;
import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
import static com.android.SdkConstants.PREFIX_THEME_REF;
import static com.android.SdkConstants.UNIT_DP;
import static com.android.SdkConstants.UNIT_SP;
import static com.android.SdkConstants.VALUE_FALSE;
import static com.android.SdkConstants.VALUE_TRUE;
import static com.android.ide.common.api.IAttributeInfo.Format.BOOLEAN;
import static com.android.ide.common.api.IAttributeInfo.Format.DIMENSION;
import static com.android.ide.common.api.IAttributeInfo.Format.ENUM;
import static com.android.ide.common.api.IAttributeInfo.Format.FLAG;
import static com.android.ide.common.api.IAttributeInfo.Format.FLOAT;
import static com.android.ide.common.api.IAttributeInfo.Format.INTEGER;
import static com.android.ide.common.api.IAttributeInfo.Format.REFERENCE;
import static com.android.ide.common.api.IAttributeInfo.Format.STRING;

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.eclipse.adt.internal.editors.common.CommonXmlEditor;
import com.android.ide.eclipse.adt.internal.editors.descriptors.AttributeDescriptor;
import com.android.utils.SdkUtils;

import org.eclipse.jface.fieldassist.ContentProposal;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

/**
 * An {@link IContentProposalProvider} which completes possible property values
 * for Android properties, completing resource strings, flag values, enum
 * values, as well as dimension units.
 */
abstract class ValueCompleter implements IContentProposalProvider {
    @Nullable
    protected abstract CommonXmlEditor getEditor();

    @NonNull
    protected abstract AttributeDescriptor getDescriptor();

    @Override
    public IContentProposal[] getProposals(String contents, int position) {
        AttributeDescriptor descriptor = getDescriptor();
        IAttributeInfo info = descriptor.getAttributeInfo();
        EnumSet<Format> formats = info.getFormats();

        List<IContentProposal> proposals = new ArrayList<IContentProposal>();

        String prefix = contents; // TODO: Go back to position inside the array?

        // TODO: If the user is typing in a number, or a number plus a prefix of a dimension unit,
        // then propose that number plus the completed dimension unit (using sp for text, dp
        // for other properties and maybe both if I'm not sure)
        if (formats.contains(STRING)
                && !contents.isEmpty()
                && (formats.size() > 1 && formats.contains(REFERENCE) ||
                        formats.size() > 2)
                && !contents.startsWith(PREFIX_RESOURCE_REF)
                && !contents.startsWith(PREFIX_THEME_REF)) {
            proposals.add(new ContentProposal(contents));
        }

        if (!contents.isEmpty() && Character.isDigit(contents.charAt(0))
                && (formats.contains(DIMENSION)
                        || formats.contains(INTEGER)
                        || formats.contains(FLOAT))) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0, n = contents.length(); i < n; i++) {
                char c = contents.charAt(i);
                if (Character.isDigit(c)) {
                    sb.append(c);
                } else {
                    break;
                }
            }

            String number = sb.toString();
            if (formats.contains(Format.DIMENSION)) {
                if (descriptor.getXmlLocalName().equals(ATTR_TEXT_SIZE)) {
                    proposals.add(new ContentProposal(number + UNIT_SP));
                }
                proposals.add(new ContentProposal(number + UNIT_DP));
            } else if (formats.contains(Format.INTEGER)) {
                proposals.add(new ContentProposal(number));
            }
            // Perhaps offer other units too -- see AndroidContentAssist.sDimensionUnits
        }

        if (formats.contains(REFERENCE) || contents.startsWith(PREFIX_RESOURCE_REF)
                || contents.startsWith(PREFIX_THEME_REF)) {
            CommonXmlEditor editor = getEditor();
            if (editor != null) {
                String[] matches = ResourceValueCompleter.computeResourceStringMatches(
                        editor,
                        descriptor, contents.substring(0, position));
                for (String match : matches) {
                    proposals.add(new ContentProposal(match));
                }
            }
        }

        if (formats.contains(FLAG)) {
            String[] values = info.getFlagValues();
            if (values != null) {
                // Flag completion
                int flagStart = prefix.lastIndexOf('|');
                String prepend = null;
                if (flagStart != -1) {
                    prepend = prefix.substring(0, flagStart + 1);
                    prefix = prefix.substring(flagStart + 1).trim();
                }

                boolean exactMatch = false;
                for (String value : values) {
                    if (prefix.equals(value)) {
                        exactMatch = true;
                        proposals.add(new ContentProposal(contents));

                        break;
                    }
                }

                if (exactMatch) {
                    prepend = contents + '|';
                    prefix = "";
                }

                for (String value : values) {
                    if (SdkUtils.startsWithIgnoreCase(value, prefix)) {
                        if (prepend != null && prepend.contains(value)) {
                            continue;
                        }
                        String match;
                        if (prepend != null) {
                            match = prepend + value;
                        } else {
                            match = value;
                        }
                        proposals.add(new ContentProposal(match));
                    }
                }
            }
        } else if (formats.contains(ENUM)) {
            String[] values = info.getEnumValues();
            if (values != null) {
                for (String value : values) {
                    if (SdkUtils.startsWithIgnoreCase(value, prefix)) {
                        proposals.add(new ContentProposal(value));
                    }
                }

                for (String value : values) {
                    if (!SdkUtils.startsWithIgnoreCase(value, prefix)) {
                        proposals.add(new ContentProposal(value));
                    }
                }
            }
        } else if (formats.contains(BOOLEAN)) {
            proposals.add(new ContentProposal(VALUE_TRUE));
            proposals.add(new ContentProposal(VALUE_FALSE));
        }

        return proposals.toArray(new IContentProposal[proposals.size()]);
    }
}
