/*
 * 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.scrplugin;

import java.util.*;

import org.apache.felix.scrplugin.om.Component;
import org.apache.felix.scrplugin.om.Property;
import org.apache.felix.scrplugin.om.metatype.AttributeDefinition;
import org.apache.felix.scrplugin.om.metatype.OCD;
import org.apache.felix.scrplugin.tags.JavaField;
import org.apache.felix.scrplugin.tags.JavaTag;
import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.StringUtils;
import org.osgi.service.cm.ConfigurationAdmin;

/**
 * Utility class for handling the properties.
 */
public class PropertyHandler {

    /**
     * This is a map using the property name as the key and
     * {@link PropertyDescription} as values.
     */
    final private Map properties = new LinkedHashMap();

    /** The component. */
    final private Component component;

    /** The ocd or null. */
    final private OCD ocd;

    public PropertyHandler(final Component c, OCD o) {
        this.component = c;
        this.ocd = o;
    }

    /**
     * Process a property.
     * @param tag       The property tag.
     * @param name      The name of the property.
     * @param javaField The corresponding java field or null.
     */
    protected void processProperty(JavaTag   tag,
                                   String    name,
                                   JavaField javaField)
    throws MojoExecutionException {
        final Property prop = new Property(tag);
        prop.setName(name);
        prop.setType(tag.getNamedParameter(Constants.PROPERTY_TYPE));
        // let's first check for a value attribute
        final String value = tag.getNamedParameter(Constants.PROPERTY_VALUE);
        if ( value != null ) {
            prop.setValue(value);
        } else {
            // now we check for a value ref attribute
            final String valueRef = tag.getNamedParameter(Constants.PROPERTY_VALUE_REF);
            if ( valueRef != null ) {
                this.setPropertyValueRef(tag, prop, valueRef);
            } else {
                // check for multivalue - these can either be values or value refs
                final List values = new ArrayList();
                final Map valueMap = tag.getNamedParameterMap();
                for (Iterator vi = valueMap.entrySet().iterator(); vi.hasNext();) {
                    final Map.Entry entry = (Map.Entry) vi.next();
                    final String key = (String) entry.getKey();
                    if (key.startsWith(Constants.PROPERTY_MULTIVALUE_PREFIX) ) {
                        values.add(entry.getValue());
                    } else if ( key.startsWith(Constants.PROPERTY_MULTIVALUE_REF_PREFIX) ) {
                        final String[] stringValues = this.getPropertyValueRef(tag, prop, (String)entry.getValue());
                        if ( stringValues != null ) {
                            for(int i=0; i<stringValues.length; i++) {
                                values.add(stringValues[i]);
                            }
                        }
                    }
                }
                if ( values.size() > 0 ) {
                    prop.setMultiValue((String[])values.toArray(new String[values.size()]));
                } else {
                    // we have no value, valueRef or values so let's try to
                    // get the value of the field if a name attribute is specified
                    final boolean isNamedParameter = tag.getNamedParameter(Constants.PROPERTY_NAME) != null
                                                  || tag.getNamedParameter(Constants.PROPERTY_NAME_REF) != null;
                    if ( isNamedParameter && javaField != null ) {
                        this.setPropertyValueRef(tag, prop, javaField.getName());
                    }
                }
            }
        }

        // property is private if explicitly marked or a well known
        // service property such as service.pid
        final boolean isPrivate = SCRDescriptorMojo.getBoolean(tag,
            Constants.PROPERTY_PRIVATE, false)
            || name.equals(org.osgi.framework.Constants.SERVICE_PID)
            || name.equals(org.osgi.framework.Constants.SERVICE_DESCRIPTION)
            || name.equals(org.osgi.framework.Constants.SERVICE_ID)
            || name.equals(org.osgi.framework.Constants.SERVICE_RANKING)
            || name.equals(org.osgi.framework.Constants.SERVICE_VENDOR)
            || name.equals(ConfigurationAdmin.SERVICE_BUNDLELOCATION)
            || name.equals(ConfigurationAdmin.SERVICE_FACTORYPID);

        // if this is an abstract component we store the extra info in the property
        if ( component.isAbstract() ) {
            prop.setPrivate(isPrivate);
            prop.setLabel(tag.getNamedParameter(Constants.PROPERTY_LABEL));
            prop.setDescription(tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION));
            prop.setCardinality(tag.getNamedParameter(Constants.PROPERTY_CARDINALITY));
        }

        // if this is a public property and the component is generating metatype info
        // store the information!
        if ( !isPrivate && ocd != null ) {
            final AttributeDefinition ad = new AttributeDefinition();
            ocd.getProperties().add(ad);
            ad.setId(prop.getName());
            ad.setType(prop.getType());

            String adName = tag.getNamedParameter(Constants.PROPERTY_LABEL);
            if ( adName == null ) {
                adName = "%" + prop.getName() + ".name";
            }
            ad.setName(adName);
            String adDesc = tag.getNamedParameter(Constants.PROPERTY_DESCRIPTION);
            if ( adDesc == null ) {
                adDesc = "%" + prop.getName() + ".description";
            }
            ad.setDescription(adDesc);
            // set optional multivalues, cardinality might be overwritten by setValues !!
            final String cValue = tag.getNamedParameter(Constants.PROPERTY_CARDINALITY);
            if (cValue != null) {
                if ("-".equals(cValue)) {
                    // unlimited vector
                    ad.setCardinality(new Integer(Integer.MIN_VALUE));
                } else if ("+".equals(cValue)) {
                   // unlimited array
                    ad.setCardinality(new Integer(Integer.MAX_VALUE));
                } else {
                    try {
                        ad.setCardinality(Integer.valueOf(cValue));
                    } catch (NumberFormatException nfe) {
                        // default to scalar in case of conversion problem
                    }
                }
            }
            ad.setDefaultValue(prop.getValue());
            ad.setDefaultMultiValue(prop.getMultiValue());

            // check options
            String[] parameters = tag.getParameters();
            Map options = null;
            for (int j=0; j < parameters.length; j++) {
                if (Constants.PROPERTY_OPTIONS.equals(parameters[j])) {
                    options = new LinkedHashMap();
                } else if (options != null) {
                    String optionLabel = parameters[j];
                    String optionValue = (j < parameters.length-2) ? parameters[j+2] : null;
                    if (optionValue != null) {
                        options.put(optionLabel, optionValue);
                    }
                    j += 2;
                }
            }
            ad.setOptions(options);
        }

        component.addProperty(prop);
    }

    /**
     * Return the name of the property.
     * The name of the property is derived by:
     * <ol>
     *   <li>looking at the attribute {@link Constants.PROPERTY_NAME}</li>
     *   <li>looking at the attribute {@link Constants.PROPERTY_NAME_REF}</li>
     *   <li>if the property is specified at a filed and the field is of type string the init value is used.</li>
     * </ol>
     *
     * @param property The property tag.
     * @param field    The corresponding field if the property is a tag of a field.
     * @return The name of the property or the defaultName
     */
    protected String getPropertyName(JavaTag tag, JavaField field)
    throws MojoExecutionException {
        // check name property
        String name = tag.getNamedParameter(Constants.PROPERTY_NAME);

        if (StringUtils.isEmpty(name)) {
            // check name ref propery
            name = tag.getNamedParameter(Constants.PROPERTY_NAME_REF);
            if (!StringUtils.isEmpty(name)) {
                final JavaField refField = this.getReferencedField(tag, name);
                final String[] values = refField.getInitializationExpression();
                if ( values == null || values.length == 0 ) {
                    throw new MojoExecutionException("Referenced field for " + name + " has no values for a property name.");
                }
                if ( values.length > 1 ) {
                    throw new MojoExecutionException("Referenced field " + name + " has more than one value for a property name.");
                }
                name = values[0];
            }

            if (StringUtils.isEmpty(name)) {
                // check field
                name = null;
                if ( field != null && "java.lang.String".equals(field.getType()) ) {
                    final String[] initValues = field.getInitializationExpression();
                    if ( initValues != null && initValues.length == 1 ) {
                        name = initValues[0];
                    }
                }
            }
        }
        // final empty check
        if ( StringUtils.isEmpty(name) ) {
            name = null;
        }
        return name;
    }

    protected void setPropertyValueRef(final JavaTag tag, Property property, String valueRef)
    throws MojoExecutionException {
        final String[] values = this.getPropertyValueRef(tag, property, valueRef);
        if ( values != null && values.length == 1 ) {
            property.setValue(values[0]);
        } else if ( values != null && values.length > 1 ) {
            property.setMultiValue(values);
        }
    }

    protected JavaField getReferencedField(final JavaTag tag, String ref)
    throws MojoExecutionException {
        int classSep = ref.lastIndexOf('.');
        JavaField field = null;
        if ( classSep == -1 ) {
            // local variable
            field = tag.getJavaClassDescription().getFieldByName(ref);
        }
        if ( field == null ) {
            field = tag.getJavaClassDescription().getExternalFieldByName(ref);
        }
        if ( field == null ) {
            throw new MojoExecutionException("Property references unknown field " + ref + " in class " + tag.getJavaClassDescription().getName());
        }
        return field;
    }

    protected String[] getPropertyValueRef(final JavaTag tag, Property prop, String valueRef)
    throws MojoExecutionException {
        final JavaField field = this.getReferencedField(tag, valueRef);

        // determine type (if not set explicitly)
        if ( prop.getType() == null ) {
            final String type = field.getType();
            if ( "java.lang.String".equals(type) ) {
                prop.setType("String");
            } else if ("java.lang.Long".equals(type) || "long".equals(type) ) {
                prop.setType("Long");
            } else if ("java.lang.Double".equals(type) || "double".equals(type) ) {
                prop.setType("Double");
            } else if ("java.lang.Float".equals(type) || "float".equals(type) ) {
                prop.setType("Float");
            } else if ("java.lang.Integer".equals(type) || "int".equals(type) ) {
                prop.setType("Integer");
            } else if ("java.lang.Byte".equals(type) || "byte".equals(type) ) {
                prop.setType("Byte");
            } else if ("java.lang.Character".equals(type) || "char".equals(type) ) {
                prop.setType("Char");
            } else if ("java.lang.Boolean".equals(type) || "boolean".equals(type) ) {
                prop.setType("Boolean");
            } else if ("java.lang.Short".equals(type) || "short".equals(type) ) {
                prop.setType("Short");
            }

        }
        return field.getInitializationExpression();
    }

    /**
     * Test if there is already a property with the same name.
     * @param property The tag.
     * @param field
     * @param isInspectedClass
     * @throws MojoExecutionException
     */
    public void testProperty(JavaTag   property,
                             JavaField field,
                             boolean   isInspectedClass)
    throws MojoExecutionException {
        final String propName = this.getPropertyName(property, field);

        if ( propName != null ) {
            if ( properties.containsKey(propName) ) {
                // if the current class is the class we are currently inspecting, we
                // have found a duplicate definition
                if ( isInspectedClass ) {
                    throw new MojoExecutionException("Duplicate definition for property " + propName + " in class " + property.getJavaClassDescription().getName());
                }
            } else {
                properties.put(propName, new PropertyDescription(property, field));
            }
        } else {
            throw new MojoExecutionException("Property has no name " + property.getSourceLocation());
        }
    }

    public void handleField(JavaField javaField, boolean isInspectedClass)
    throws MojoExecutionException {
        final JavaTag tag = javaField.getTagByName(Constants.PROPERTY);
        if (tag != null) {
            this.testProperty(tag, javaField, isInspectedClass);
        }
    }

    /**
     * Process all found properties for the component.
     * @throws MojoExecutionException
     */
    public void processProperties(final Map globalProperties)
    throws MojoExecutionException {
        final Iterator propIter = properties.entrySet().iterator();
        while ( propIter.hasNext() ) {
            final Map.Entry entry = (Map.Entry)propIter.next();
            final String propName = entry.getKey().toString();
            final PropertyDescription desc = (PropertyDescription)entry.getValue();
            this.processProperty(desc.propertyTag, propName, desc.field);
        }
        // apply pre configured global properties
        if ( globalProperties != null ) {
            final Iterator globalPropIter = globalProperties.entrySet().iterator();
            while ( globalPropIter.hasNext() ) {
                final Map.Entry entry = (Map.Entry)globalPropIter.next();
                final String name = entry.getKey().toString();

                // check if the service already provides this property
                if ( !properties.containsKey(name) && entry.getValue() != null ) {
                    final String value = entry.getValue().toString();

                    final Property p = new Property();
                    p.setName(name);
                    p.setValue(value);
                    p.setType("String");
                    p.setPrivate(true);
                    component.addProperty(p);

                }
            }
        }
    }

    protected static final class PropertyDescription {
        public final JavaTag propertyTag;
        public final JavaField field;

        public PropertyDescription(final JavaTag p, final JavaField f) {
            this.propertyTag = p;
            this.field = f;
        }
    }
}
