/*
 * 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.webconsole.internal.configuration;


import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.felix.utils.json.JSONWriter;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.metatype.AttributeDefinition;


/**
 * The <code>ConfigManagerBase</code> is the base class for the
 * ConfigurationAdmin support in the web console. It provides various helper
 * methods mostly with respect to using the MetaTypeService to access
 * configuration descriptions.
 */
class MetaTypeSupport
{


    /**
     * Marker value of password fields used as dummy values and
     * indicating unmodified values.
     */
    static final String PASSWORD_PLACEHOLDER_VALUE = "unmodified"; //$NON-NLS-1$


    static Bundle getBundle( final BundleContext bundleContext, final String bundleLocation )
    {
        if ( bundleLocation == null )
        {
            return null;
        }

        Bundle[] bundles = bundleContext.getBundles();
        for ( int i = 0; i < bundles.length; i++ )
        {
            if ( bundleLocation.equals( bundles[i].getLocation() ) )
            {
                return bundles[i];
            }
        }

        return null;
    }


    static void attributeToJson( final JSONWriter json, final PropertyDescriptor ad, final Object propValue )
            throws IOException
    {
        json.object();

        Object value;
        if ( propValue != null )
        {
            value = propValue;
        }
        else if ( ad.getDefaultValue() != null )
        {
            value = ad.getDefaultValue();
        }
        else if ( ad.getCardinality() == 0 )
        {
            value = ""; //$NON-NLS-1$
        }
        else
        {
            value = new String[0];
        }

        json.key( "name" ); //$NON-NLS-1$
        json.value( ad.getName() );
        json.key( "optional" ); //$NON-NLS-1$
        json.value( ad.isOptional() );
        json.key( "is_set" ); //$NON-NLS-1$
        json.value( propValue != null );

        // attribute type - overwrite metatype provided type
        // if the property name contains "password" and the
        // type is string
        int propertyType = getAttributeType( ad );

        json.key( "type" ); //$NON-NLS-1$
        if ( ad.getOptionLabels() != null && ad.getOptionLabels().length > 0 )
        {
            json.object();
            json.key( "labels" ); //$NON-NLS-1$
            json.value( Arrays.asList( ad.getOptionLabels() ) );
            json.key( "values" ); //$NON-NLS-1$
            json.value( Arrays.asList( ad.getOptionValues() ) );
            json.endObject();
        }
        else
        {
            json.value( propertyType );
        }

        // unless the property is of password type, send it
        final boolean isPassword = propertyType == AttributeDefinition.PASSWORD;
        if ( ad.getCardinality() == 0 )
        {
            // scalar
            if ( isPassword )
            {
                value = PASSWORD_PLACEHOLDER_VALUE;
            }
            else if ( value instanceof Vector )
            {
                value = ( ( Vector ) value ).get( 0 );
            }
            else if ( value.getClass().isArray() )
            {
                value = Array.get( value, 0 );
            }
            json.key( "value" ); //$NON-NLS-1$
            json.value( value );
        }
        else
        {
            json.key( "values" ); //$NON-NLS-1$
            json.array();
            final List list = toList( value );
            final Iterator iter = list.iterator();
            while ( iter.hasNext() )
            {
                final Object val = iter.next();
                if ( isPassword )
                {
                    json.value(PASSWORD_PLACEHOLDER_VALUE);
                }
                else
                {
                    json.value(val);
                }
            }
            json.endArray();
        }

        if ( ad.getDescription() != null )
        {
            json.key( "description" ); //$NON-NLS-1$
            json.value( ad.getDescription() + " (" + ad.getID() + ")" ); //$NON-NLS-1$ //$NON-NLS-2$
        }

        json.endObject();
    }


    private static List toList( Object value )
    {
        if ( value instanceof Vector )
        {
            return ( Vector ) value;
        }
        else if ( value.getClass().isArray() )
        {
            if ( value.getClass().getComponentType().isPrimitive() )
            {
                final int len = Array.getLength( value );
                final Object[] tmp = new Object[len];
                for ( int j = 0; j < len; j++ )
                {
                    tmp[j] = Array.get( value, j );
                }
                value = tmp;
            }
            return Arrays.asList( ( Object[] ) value );
        }
        else
        {
            return Collections.singletonList( value );
        }
    }


    static PropertyDescriptor createAttributeDefinition( final String id, final Object value )
    {
        int attrType;
        int attrCardinality;
        Class type;

        if ( value == null )
        {
            attrCardinality = 0;
            type = String.class;
        }
        else if ( value instanceof Collection )
        {
            attrCardinality = Integer.MIN_VALUE;
            Collection coll = ( Collection ) value;
            if ( coll.isEmpty() )
            {
                type = String.class;
            }
            else
            {
                type = coll.iterator().next().getClass();
            }
        }
        else if ( value.getClass().isArray() )
        {
            attrCardinality = Integer.MAX_VALUE;
            type = value.getClass().getComponentType();
        }
        else
        {
            attrCardinality = 0;
            type = value.getClass();
        }

        if ( type == Boolean.class || type == Boolean.TYPE )
        {
            attrType = AttributeDefinition.BOOLEAN;
        }
        else if ( type == Byte.class || type == Byte.TYPE )
        {
            attrType = AttributeDefinition.BYTE;
        }
        else if ( type == Character.class || type == Character.TYPE )
        {
            attrType = AttributeDefinition.CHARACTER;
        }
        else if ( type == Double.class || type == Double.TYPE )
        {
            attrType = AttributeDefinition.DOUBLE;
        }
        else if ( type == Float.class || type == Float.TYPE )
        {
            attrType = AttributeDefinition.FLOAT;
        }
        else if ( type == Long.class || type == Long.TYPE )
        {
            attrType = AttributeDefinition.LONG;
        }
        else if ( type == Integer.class || type == Integer.TYPE )
        {
            attrType = AttributeDefinition.INTEGER;
        }
        else if ( type == Short.class || type == Short.TYPE )
        {
            attrType = AttributeDefinition.SHORT;
        }
        else
        {
            attrType = AttributeDefinition.STRING;
        }

        return new PropertyDescriptor( id, attrType, attrCardinality );
    }


    static int getAttributeType( final PropertyDescriptor ad )
    {
        return ad.getType();
    }


    /**
     * @throws NumberFormatException If the value cannot be converted to
     *      a number and type indicates a numeric type
     */
    static final Object toType( int type, String value )
    {
        switch ( type )
        {
        case AttributeDefinition.BOOLEAN:
            return Boolean.valueOf( value );
        case AttributeDefinition.BYTE:
            return Byte.valueOf( value );
        case AttributeDefinition.CHARACTER:
            char c = ( value.length() > 0 ) ? value.charAt( 0 ) : 0;
            return new Character( c );
        case AttributeDefinition.DOUBLE:
            return Double.valueOf( value );
        case AttributeDefinition.FLOAT:
            return Float.valueOf( value );
        case AttributeDefinition.LONG:
            return Long.valueOf( value );
        case AttributeDefinition.INTEGER:
            return Integer.valueOf( value );
        case AttributeDefinition.SHORT:
            return Short.valueOf( value );
        default:
            // includes AttributeDefinition.STRING
            // includes AttributeDefinition.PASSWORD
            return value;
        }
    }


    static void setPasswordProps( final Vector vec, final String[] properties, Object props )
    {
        List propList = ( props == null ) ? new ArrayList() : toList( props );
        for ( int i = 0; i < properties.length; i++ )
        {
            if ( PASSWORD_PLACEHOLDER_VALUE.equals( properties[i] ) )
            {
                if ( i < propList.size() && propList.get( i ) != null )
                {
                    vec.add( propList.get( i ) );
                }
            }
            else
            {
                vec.add( properties[i] );
            }
        }
    }


    static final Object toArray( int type, Vector values )
    {
        int size = values.size();

        // short cut for string array
        if ( type == AttributeDefinition.STRING || type == AttributeDefinition.PASSWORD )
        {
            return values.toArray( new String[size] );
        }

        Object array;
        switch ( type )
        {
        case AttributeDefinition.BOOLEAN:
            array = new boolean[size];
            break;
        case AttributeDefinition.BYTE:
            array = new byte[size];
            break;
        case AttributeDefinition.CHARACTER:
            array = new char[size];
            break;
        case AttributeDefinition.DOUBLE:
            array = new double[size];
            break;
        case AttributeDefinition.FLOAT:
            array = new float[size];
            break;
        case AttributeDefinition.LONG:
            array = new long[size];
            break;
        case AttributeDefinition.INTEGER:
            array = new int[size];
            break;
        case AttributeDefinition.SHORT:
            array = new short[size];
            break;
        default:
            // unexpected, but assume string
            array = new String[size];
        }

        for ( int i = 0; i < size; i++ )
        {
            Array.set( array, i, values.get( i ) );
        }

        return array;
    }

}
