/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.apache.felix.metatype;

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

import org.apache.felix.metatype.internal.Activator;
import org.osgi.service.log.LogService;
import org.osgi.service.metatype.AttributeDefinition;

/**
 * The <code>AD</code> class represents the <code>AD</code> element of the
 * meta type descriptor.
 *
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class AD extends OptionalAttributes
{

    /**
     * The message returned from the {@link #validate(String)} method if the
     * value is not any of the specified {@link #getOptionValues() option values}
     * (value is "%not a valid option").
     */
    public static final String VALIDATE_NOT_A_VALID_OPTION = "%not a valid option";

    /**
     * The message returned from the {@link #validate(String)} method if the
     * value is invalid considering its type (value is "%invalid value").
     */
    public static final String VALIDATE_INVALID_VALUE = "%invalid value";

    /**
     * The message returned from the {@link #validate(String)} method if the
     * value is greater than the specified {@link #getMax() maximum value}
     * (value is "%greater than maximum").
     */
    public static final String VALIDATE_GREATER_THAN_MAXIMUM = "%greater than maximum";

    /**
     * The message returned from the {@link #validate(String)} method if the
     * value is less than the specified {@link #getMin() minimum value}
     * (value is "%less than minimum").
     */
    public static final String VALIDATE_LESS_THAN_MINIMUM = "%less than minimum";

    /**
     * The message returned from the {@link #validate(String)} method if the
     * value is null or cannot be converted to an attribute value and a value
     * is {@link #isRequired() required} (value is "%missing required value").
     */
    public static final String VALIDATE_MISSING = "%missing required value";

    private String id;
    private String name;
    private String description;
    private int type;
    private int cardinality = 0;
    private String[] optionLabels;
    private String[] optionValues;
    private String[] defaultValue;
    private String min;
    private String max;
    private boolean isRequired = true;

    public String getID()
    {
        return id;
    }

    public String getName()
    {
        return name;
    }

    public String getDescription()
    {
        return description;
    }

    public int getType()
    {
        return type;
    }

    public int getCardinality()
    {
        return cardinality;
    }

    public String[] getOptionLabels()
    {
        return optionLabels;
    }

    public String[] getOptionValues()
    {
        return optionValues;
    }

    public String[] getDefaultValue()
    {
        return defaultValue;
    }

    public String getMin()
    {
        return min;
    }

    public String getMax()
    {
        return max;
    }

    public boolean isRequired()
    {
        return isRequired;
    }

    /**
     * Implements validation of the <code>valueString</code> and returns an
     * indication of the validation result.
     *
     * @param valueString The string representation of the value to validate,
     *        can be <code>null</code>.
     *
     * @return <code>null</code> if no validation is performed, <tt>""</tt> if
     *         the value is accepted as valid, or a non-empty string
     *         indicating a validation problem was found.
     *
     * @see ADValidator#validate(AD, String)
     * @see #VALIDATE_GREATER_THAN_MAXIMUM
     * @see #VALIDATE_NOT_A_VALID_OPTION
     * @see #VALIDATE_LESS_THAN_MINIMUM
     * @see #VALIDATE_INVALID_VALUE
     * @see #VALIDATE_MISSING
     */
    public String validate(String valueString)
    {
        return ADValidator.validate(this, valueString);
    }

    //--------- Setters for setting up this instance --------------------------

    /**
     * @param id the id to set
     */
    public void setID(String id)
    {
        this.id = id;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name)
    {
        this.name = name;
    }

    /**
     * @param description the description to set
     */
    public void setDescription(String description)
    {
        this.description = description;
    }

    /**
     * @param typeString the type to set
     */
    public void setType(String typeString)
    {
        this.type = toType(typeString);
    }

    /**
     * @param cardinality the cardinality to set
     */
    public void setCardinality(int cardinality)
    {
        this.cardinality = cardinality;
    }

    /**
     * @param options the options to set
     */
    public void setOptions(Map options)
    {
        optionLabels = new String[options.size()];
        optionValues = new String[options.size()];
        int i = 0;
        for (Iterator oi = options.entrySet().iterator(); oi.hasNext(); i++)
        {
            Map.Entry entry = (Map.Entry) oi.next();
            optionValues[i] = String.valueOf(entry.getKey());
            optionLabels[i] = String.valueOf(entry.getValue());
        }
    }

    /**
     * Sets the default value(s) for this AD.
     * <p>
     * NOTE: this method is depending on the value of {@link #getCardinality()}! Make sure that the
     * cardinality is properly set <b>before</b> calling this method.
     * </p>
     * 
     * @param defaultValue the default value to set, as encoded string-value (using comma's as separator), can be <code>null</code>.
     */
    public void setDefaultValue(String defaultValue)
    {
        setDefaultValue(splitList(defaultValue), Math.abs(this.cardinality));
    }

    /**
     * @param min the min to set
     */
    public void setMin(String min)
    {
        this.min = min;
    }

    /**
     * @param max the max to set
     */
    public void setMax(String max)
    {
        this.max = max;
    }

    /**
     * @param isRequired the isRequired to set
     */
    public void setRequired(boolean isRequired)
    {
        this.isRequired = isRequired;
    }

    public static int toType(String typeString)
    {
        if ("String".equals(typeString))
        {
            return AttributeDefinition.STRING;
        }
        else if ("Long".equals(typeString))
        {
            return AttributeDefinition.LONG;
        }
        else if ("Double".equals(typeString))
        {
            return AttributeDefinition.DOUBLE;
        }
        else if ("Float".equals(typeString))
        {
            return AttributeDefinition.FLOAT;
        }
        else if ("Integer".equals(typeString))
        {
            return AttributeDefinition.INTEGER;
        }
        else if ("Byte".equals(typeString))
        {
            return AttributeDefinition.BYTE;
        }
        else if ("Character".equals(typeString) || "Char".equals(typeString))
        {
            return AttributeDefinition.CHARACTER;
        }
        else if ("Boolean".equals(typeString))
        {
            return AttributeDefinition.BOOLEAN;
        }
        else if ("Short".equals(typeString))
        {
            return AttributeDefinition.SHORT;
        }
        else if ("Password".equals(typeString))
        {
            return AttributeDefinition.PASSWORD;
        }

        // finally fall back to string for illegal values
        return AttributeDefinition.STRING;
    }

    public static String[] splitList(String listString)
    {
        if (listString == null)
        {
            return null;
        }
        else if (listString.length() == 0)
        {
            return new String[] { "" };
        }

        List strings = new ArrayList();
        StringBuffer sb = new StringBuffer();

        int length = listString.length();
        boolean escaped = false;
        int spaceCount = 0;
        boolean start = true;
        for (int i = 0; i < length; i++)
        {
            char ch = listString.charAt(i);
            final boolean isWhitespace = Character.isWhitespace(ch);
            if (start)
            {
                if (isWhitespace)
                {
                    continue;
                }
                start = false;
            }
            if (ch == '\\')
            {
                if (!escaped)
                {
                    escaped = true;
                    continue;
                }
            }
            else if (ch == ',')
            {
                if (!escaped)
                {
                    // unescaped comma, this is a string delimiter...
                    strings.add(sb.toString());
                    sb.setLength(0);
                    start = true;
                    spaceCount = 0;
                    continue;
                }
            }
            else if (ch == ' ')
            {
                // space is only ignored at beginning and end but not if escaped
                if (!escaped)
                {
                    spaceCount++;
                    continue;
                }
            }
            else if (isWhitespace)
            {
                // Other whitespaces are ignored...
                continue;
            }

            if (spaceCount > 0)
            {
                for (int m = 0; m < spaceCount; m++)
                {
                    sb.append(" ");
                }
                spaceCount = 0;
            }
            sb.append(ch);
            escaped = false;
        }

        // Always add the last string, as it contains everything after the last comma...
        strings.add(sb.toString());

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

    protected Comparable convertToType(final String value)
    {
        if (value != null && value.length() > 0)
        {
            try
            {
                switch (getType())
                {
                    case AttributeDefinition.BOOLEAN:
                        // Boolean is only Comparable starting with Java 5
                        return new ComparableBoolean(value);
                    case AttributeDefinition.CHARACTER:
                        return new Character(value.charAt(0));
                    case AttributeDefinition.BYTE:
                        return Byte.valueOf(value);
                    case AttributeDefinition.SHORT:
                        return Short.valueOf(value);
                    case AttributeDefinition.INTEGER:
                        return Integer.valueOf(value);
                    case AttributeDefinition.LONG:
                        return Long.valueOf(value);
                    case AttributeDefinition.FLOAT:
                        return Float.valueOf(value);
                    case AttributeDefinition.DOUBLE:
                        return Double.valueOf(value);
                    case AttributeDefinition.STRING:
                    case AttributeDefinition.PASSWORD:
                    default:
                        return value;
                }
            }
            catch (NumberFormatException nfe)
            {
                Activator.log(LogService.LOG_INFO, "Cannot convert value '" + value + "'", nfe);
            }
        }

        return null;
    }

    /**
     * @param values the defaultValue to set
     */
    protected void setDefaultValue(String[] values, int cardinality)
    {
        if (values != null)
        {
            int count = 0;
            int max = Math.min(values.length, Math.max(1, cardinality));
            for (int i = 0; count < max && i < values.length; i++)
            {
                if ("".equals(ADValidator.validate(this, values[i])))
                {
                    count++;
                }
                else
                {
                    values[i] = null;
                }
            }
            if (count == 0)
            {
                values = cardinality == 0 ? null : new String[0];
            }
            else if (count != values.length)
            {
                String[] filterValues = new String[count];
                int index = 0;
                for (int i = 0; index < count && i < values.length; i++)
                {
                    if (values[i] != null)
                    {
                        filterValues[index] = values[i];
                        index++;
                    }
                }
                values = filterValues;
            }
        }
        this.defaultValue = values;
    }

    private static class ComparableBoolean implements Comparable
    {
        private boolean value;

        ComparableBoolean(String boolValue)
        {
            value = Boolean.valueOf(boolValue).booleanValue();
        }

        public int compareTo(Object obj)
        {
            ComparableBoolean cb = (ComparableBoolean) obj;
            return (cb.value == value ? 0 : (value ? 1 : -1));
        }
    }
}
