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


import java.io.IOException;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;

import org.apache.felix.cm.PersistenceManager;
import org.apache.felix.cm.impl.helper.TargetedPID;
import org.osgi.framework.Constants;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.log.LogService;


/**
 * The <code>ConfigurationImpl</code> is the backend implementation of the
 * Configuration Admin Service Specification <i>Configuration object</i>
 * (section 104.4). Instances of this class are shared by multiple instances of
 * the {@link ConfigurationAdapter} class, whose instances are actually returned
 * to clients.
 */
public class ConfigurationImpl
{

    /*
     * Concurrency note: There is a slight (but real) chance of a race condition
     * between a configuration update and a ManagedService[Factory] registration.
     * Per the specification a ManagedService must be called with configuration
     * or null when registered and a ManagedService must be called with currently
     * existing configuration when registered. Also the ManagedService[Factory]
     * must be updated when the configuration is updated.
     *
     * Consider now this situation of two threads T1 and T2:
     *
     *    T1. create and update configuration
     *      ConfigurationImpl.update persists configuration and sets field
     *      Thread preempted
     *
     *    T2. ManagedServiceUpdate constructor reads configuration
     *      Uses configuration already persisted by T1 for update
     *      Schedules task to update service with the configuration
     *
     *    T1. Runs again creating the UpdateConfiguration task with the
     *      configuration persisted before being preempted
     *      Schedules task to update service
     *
     *    Update Thread:
     *      Updates ManagedService with configuration prepared by T2
     *      Updates ManagedService with configuration prepared by T1
     *
     * The correct behaviour would be here, that the second call to update
     * would not take place. We cannot at this point in time easily fix
     * this issue. Also, it seems that changes for this to happen are
     * small.
     *
     * This class provides modification counter (lastModificationTime)
     * which is incremented on each change of the configuration. This
     * helps the update tasks in the ConfigurationManager to log the
     * revision of the configuration supplied.
     */

    /**
     * The name of a synthetic property stored in the persisted configuration
     * data to indicate that the configuration data is new, that is created but
     * never updated (value is "_felix_.cm.newConfiguration").
     * <p>
     * This special property is stored by the
     * {@link #ConfigurationImpl(ConfigurationManager, PersistenceManager, String, String, String)}
     * constructor, when the configuration is first created and persisted and is
     * interpreted by the
     * {@link #ConfigurationImpl(ConfigurationManager, PersistenceManager, Dictionary)}
     * method when the configuration data is loaded in a new object.
     * <p>
     * The goal of this property is to keep the information on whether
     * configuration data is new (but persisted as per the spec) or has already
     * been assigned with possible no data.
     */
    private static final String CONFIGURATION_NEW = "_felix_.cm.newConfiguration";

    private static final String PROPERTY_LOCKED = ":org.apache.felix.configadmin.locked:";

    private static final String PROPERTY_REVISION = ":org.apache.felix.configadmin.revision:";

    /**
     * The factory PID of this configuration or <code>null</code> if this
     * is not a factory configuration.
     */
    private final TargetedPID factoryPID;

    /**
     * The statically bound bundle location, which is set explicitly by calling
     * the Configuration.setBundleLocation(String) method or when the
     * configuration was created with the two-argument method.
     */
    private volatile String staticBundleLocation;

    /**
     * The bundle location from dynamic binding. This value is set as the
     * configuration or factory is assigned to a ManagedService[Factory].
     */
    private volatile String dynamicBundleLocation;

    /**
     * The configuration data of this configuration instance. This is a private
     * copy of the properties of which a copy is made when the
     * {@link #getProperties()} method is called. This field is
     * <code>null</code> if the configuration has been created and never been
     * updated with acutal configuration properties.
     */
    private volatile CaseInsensitiveDictionary properties;

    /**
     * Flag indicating that this configuration has been deleted.
     *
     * @see #isDeleted()
     */
    private volatile boolean isDeleted;

    /**
     * Configuration revision counter incremented each time the
     * {@link #properties} is set (in the constructor or the
     * {@link #configure(Dictionary)} method. This counter is
     * persisted transparently so that {@link NotCachablePersistenceManager}
     * can provide a proper change count. The persistence is forward
     * compatible such that previously persisted configurations are
     * handled gracefully.
     */
    private volatile long revision;

    private volatile boolean locked;


    /**
     * The {@link ConfigurationManager configuration manager} instance which
     * caused this configuration object to be created.
     */
    private final ConfigurationManager configurationManager;

    // the persistence manager storing this factory mapping
    private final PersistenceManager persistenceManager;

    // the basic ID of this instance
    private final TargetedPID baseId;



    public ConfigurationImpl( ConfigurationManager configurationManager, PersistenceManager persistenceManager,
        Dictionary<String, Object> properties )
    {
        if ( configurationManager == null )
        {
            throw new IllegalArgumentException( "ConfigurationManager must not be null" );
        }

        if ( persistenceManager == null )
        {
            throw new IllegalArgumentException( "PersistenceManager must not be null" );
        }

        this.configurationManager = configurationManager;
        this.persistenceManager = persistenceManager;
        this.baseId = new TargetedPID( ( String ) properties.remove( Constants.SERVICE_PID ) );

        final String factoryPid = ( String ) properties.remove( ConfigurationAdmin.SERVICE_FACTORYPID );
        this.factoryPID = ( factoryPid == null ) ? null : new TargetedPID( factoryPid );
        this.isDeleted = false;

        // set bundle location from persistence and/or check for dynamic binding
        this.staticBundleLocation = ( String ) properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION ) ;
        this.dynamicBundleLocation = configurationManager.getDynamicBundleLocation( this.baseId.toString() );

        // set the properties internally
        configureFromPersistence( properties );
    }


    ConfigurationImpl( ConfigurationManager configurationManager, PersistenceManager persistenceManager, String pid,
        String factoryPid, String bundleLocation ) throws IOException
    {
        if ( configurationManager == null )
        {
            throw new IllegalArgumentException( "ConfigurationManager must not be null" );
        }

        if ( persistenceManager == null )
        {
            throw new IllegalArgumentException( "PersistenceManager must not be null" );
        }

        this.configurationManager = configurationManager;
        this.persistenceManager = persistenceManager;
        this.baseId = new TargetedPID( pid );

        this.factoryPID = ( factoryPid == null ) ? null : new TargetedPID( factoryPid );
        this.isDeleted = false;

        // set bundle location from persistence and/or check for dynamic binding
        this.staticBundleLocation = bundleLocation;
        this.dynamicBundleLocation = configurationManager.getDynamicBundleLocation( this.baseId.toString() );

        // first "update"
        this.properties = null;
        this.revision = 1;

        // this is a new configuration object, store immediately unless
        // the new configuration object is created from a factory, in which
        // case the configuration is only stored when first updated
        if ( factoryPid == null )
        {
            storeNewConfiguration();
        }
    }

    /**
     * Returns <code>true</code> if the ConfigurationManager of this
     * configuration is still active.
     */
    boolean isActive()
    {
        return configurationManager.isActive();
    }


    void storeSilently()
    {
        try
        {
            this.store();
        }
        catch ( IOException ioe )
        {
            Log.logger.log( LogService.LOG_ERROR, "Persisting ID {0} failed", new Object[]
                { this.baseId, ioe } );
        }
    }


    static protected void replaceProperty( Dictionary<String, Object> properties, String key, String value )
    {
        if ( value == null )
        {
            properties.remove( key );
        }
        else
        {
            properties.put( key, value );
        }
    }

    public void delete() throws IOException
    {
        this.isDeleted = true;
        this.persistenceManager.delete( this.getPidString() );
        configurationManager.setDynamicBundleLocation( this.getPidString(), null );
        configurationManager.deleted( this );
    }


    public String getPidString()
    {
        return this.baseId.toString();
    }


    public TargetedPID getPid()
    {
        return this.baseId;
    }


    public String getFactoryPidString()
    {
        return (factoryPID == null) ? null : factoryPID.toString();
    }


    public TargetedPID getFactoryPid()
    {
        return factoryPID;
    }


    /**
     * Returns the "official" bundle location as visible from the outside
     * world of code calling into the Configuration.getBundleLocation() method.
     * <p>
     * In other words: The {@link #getStaticBundleLocation()} is returned if
     * not <code>null</code>. Otherwise the {@link #getDynamicBundleLocation()}
     * is returned (which may also be <code>null</code>).
     */
    String getBundleLocation()
    {
        if ( staticBundleLocation != null )
        {
            return staticBundleLocation;
        }

        return dynamicBundleLocation;
    }


    String getDynamicBundleLocation()
    {
        return dynamicBundleLocation;
    }


    String getStaticBundleLocation()
    {
        return staticBundleLocation;
    }


    void setStaticBundleLocation( final String bundleLocation )
    {
        // CM 1.4; needed for bundle location change at the end
        final String oldBundleLocation = getBundleLocation();

        // 104.15.2.8 The bundle location will be set persistently
        this.staticBundleLocation = bundleLocation;
        storeSilently();

        // FELIX-3360: Always clear dynamic binding if a new static
        // location is set. The static location is the relevant binding
        // for a configuration unless it is not explicitly set.
        setDynamicBundleLocation( null, false );

        // CM 1.4
        this.configurationManager.locationChanged( this, oldBundleLocation );
    }


    void setDynamicBundleLocation( final String bundleLocation, final boolean dispatchConfiguration )
    {
        // CM 1.4; needed for bundle location change at the end
        final String oldBundleLocation = getBundleLocation();

        this.dynamicBundleLocation = bundleLocation;
        this.configurationManager.setDynamicBundleLocation( this.getPidString(), bundleLocation );

        // CM 1.4
        if ( dispatchConfiguration )
        {
            this.configurationManager.locationChanged( this, oldBundleLocation );

        }
    }


    /**
     * Dynamically binds this configuration to the given location unless
     * the configuration is already bound (statically or dynamically). In
     * the case of this configuration to be dynamically bound a
     * <code>CM_LOCATION_CHANGED</code> event is dispatched.
     */
    void tryBindLocation( final String bundleLocation )
    {
        if ( this.getBundleLocation() == null )
        {
            Log.logger.log( LogService.LOG_DEBUG, "Dynamically binding config {0} to {1}", new Object[]
                { getPidString(), bundleLocation } );
            setDynamicBundleLocation( bundleLocation, true );
        }
    }


    /**
     * Returns an optionally deep copy of the properties of this configuration
     * instance.
     * <p>
     * This method returns a copy of the internal dictionary. If the
     * <code>deepCopy</code> parameter is true array and collection values are
     * copied into new arrays or collections. Otherwise just a new dictionary
     * referring to the same objects is returned.
     *
     * @param deepCopy
     *            <code>true</code> if a deep copy is to be returned.
     * @return the configuration properties
     */
    public Dictionary<String, Object> getProperties( boolean deepCopy )
    {
        // no properties yet
        if ( properties == null )
        {
            return null;
        }

        CaseInsensitiveDictionary props = new CaseInsensitiveDictionary( properties, deepCopy );

        // fix special properties (pid, factory PID, bundle location)
        setAutoProperties( props, false );

        return props;
    }


    /* (non-Javadoc)
     * @see org.osgi.service.cm.Configuration#update()
     */
    public void update() throws IOException
    {
        // read configuration from persistence (again)
        if ( persistenceManager.exists( getPidString() ) )
        {
            @SuppressWarnings("unchecked")
            Dictionary<String, Object> properties = persistenceManager.load( getPidString() );

            // ensure serviceReference pid
            String servicePid = ( String ) properties.get( Constants.SERVICE_PID );
            if ( servicePid != null && !getPidString().equals( servicePid ) )
            {
                throw new IOException( "PID of configuration file does match requested PID; expected " + getPidString()
                    + ", got " + servicePid );
            }

            // we're doing a local update, so override the properties revision
            properties.put( PROPERTY_REVISION, Long.valueOf(getRevision()) );
            configureFromPersistence( properties );
        }

        // update the service but do not fire an CM_UPDATED event
        configurationManager.updated( this, false );
    }


    /**
     * @see org.osgi.service.cm.Configuration#update(java.util.Dictionary)
     */
    public void update( Dictionary<String, ?> properties ) throws IOException
    {
        CaseInsensitiveDictionary newProperties = new CaseInsensitiveDictionary( properties );

        Log.logger.log( LogService.LOG_DEBUG, "Updating config {0} with {1}", new Object[]
            { getPidString(), newProperties } );

        setAutoProperties( newProperties, true );

        // persist new configuration
        newProperties.put( PROPERTY_REVISION, Long.valueOf(getRevision()) );
        persistenceManager.store( getPidString(), newProperties );

        // finally assign the configuration for use
        configure( newProperties );

        // update the service and fire an CM_UPDATED event
        configurationManager.updated( this, true );
    }


    //---------- Object overwrites --------------------------------------------

    @Override
    public boolean equals( Object obj )
    {
        if ( obj == this )
        {
            return true;
        }

        if ( obj instanceof Configuration )
        {
            return getPidString().equals( ( ( Configuration ) obj ).getPid() );
        }

        return false;
    }


    @Override
    public int hashCode()
    {
        return getPidString().hashCode();
    }


    @Override
    public String toString()
    {
        return "Configuration PID=" + getPidString() + ", factoryPID=" + factoryPID + ", bundleLocation=" + getBundleLocation();
    }


    // ---------- private helper -----------------------------------------------

    /**
     * Stores the configuration if it is a newly factory configuration
     * which has not been persisted yet.
     * <p>
     * This is used to ensure a configuration c as in
     * <pre>
     * Configuration cf = cm.createFactoryConfiguration(factoryPid);
     * Configuration c = cm.getConfiguration(cf.getPid());
     * </pre>
     * is persisted after <code>getConfiguration</code> while
     * <code>createConfiguration</code> alone does not persist yet.
     */
    void ensureFactoryConfigPersisted() throws IOException
    {
        if ( this.factoryPID != null && isNew() && !persistenceManager.exists( getPidString() ) )
        {
            storeNewConfiguration();
        }
    }


    /**
     * Persists a new (freshly created) configuration with a marker for
     * it to be a new configuration.
     *
     * @throws IOException If an error occurrs storing the configuraiton
     */
    private void storeNewConfiguration() throws IOException
    {
        Dictionary<String, Object> props = new Hashtable<>();
        setAutoProperties( props, true );
        props.put( CONFIGURATION_NEW, Boolean.TRUE );
        props.put( PROPERTY_REVISION, Long.valueOf(getRevision()) );
        persistenceManager.store( getPidString(), props );
    }


    void store() throws IOException
    {
        // we don't need a deep copy, since we are not modifying
        // any value in the dictionary itself. we are just adding
        // properties to it, which are required for storing
        Dictionary<String, Object> props = getProperties( false );

        // if this is a new configuration, we just use an empty Dictionary
        if ( props == null )
        {
            props = new Hashtable<>();

            // add automatic properties including the bundle location (if
            // statically bound)
            setAutoProperties( props, true );
        }
        else
        {
            replaceProperty( props, ConfigurationAdmin.SERVICE_BUNDLELOCATION, getStaticBundleLocation() );
        }

        if ( this.locked )
        {
            props.put(PROPERTY_LOCKED, this.locked);
        }
        else
        {
            props.remove(PROPERTY_LOCKED);
        }
        // only store now, if this is not a new configuration
        props.put( PROPERTY_REVISION, Long.valueOf(getRevision()) );
        persistenceManager.store( getPidString(), props );
    }


    /**
     * Returns the revision of this configuration object.
     * <p>
     * When getting both the configuration properties and this revision
     * counter, the two calls should be synchronized on this instance to
     * ensure configuration values and revision counter match.
     */
    public long getRevision()
    {
        return revision;
    }


    /**
     * Returns <code>false</code> if this configuration contains configuration
     * properties. Otherwise <code>true</code> is returned and this is a
     * newly creted configuration object whose {@link #update(Dictionary)}
     * method has never been called.
     */
    boolean isNew()
    {
        return properties == null;
    }


    /**
     * Returns <code>true</code> if this configuration has already been deleted
     * on the persistence.
     */
    boolean isDeleted()
    {
        return isDeleted;
    }


    private void configureFromPersistence( Dictionary<String, Object> properties )
    {
        // if the this is not an empty/new configuration, accept the properties
        // otherwise just set the properties field to null
        if ( properties.get( CONFIGURATION_NEW ) == null )
        {
            configure( properties );
        }
        else
        {
            configure( null );
        }
    }

    private void configure( final Dictionary<String, Object> properties )
    {
        final Object revisionValue = properties == null ? null : properties.get(PROPERTY_REVISION);
        final Object lockedValue = properties == null ? null : properties.get(PROPERTY_LOCKED);
        if ( lockedValue != null )
        {
            this.locked = true;
        }
        final CaseInsensitiveDictionary newProperties;
        if ( properties == null )
        {
            newProperties = null;
        }
        else
        {
            // remove predefined properties
            clearAutoProperties( properties );

            // ensure CaseInsensitiveDictionary
            if ( properties instanceof CaseInsensitiveDictionary )
            {
                newProperties = ( CaseInsensitiveDictionary ) properties;
            }
            else
            {
                newProperties = new CaseInsensitiveDictionary( properties );
            }
        }

        synchronized ( this )
        {
            this.properties = newProperties;
            this.revision = (revisionValue != null) ? 1 + ((Long)revisionValue).longValue() : ++revision ;
        }
    }


    void setAutoProperties( Dictionary<String, Object> properties, boolean withBundleLocation )
    {
        // set pid and factory pid in the properties
        replaceProperty( properties, Constants.SERVICE_PID, getPidString() );
        replaceProperty( properties, ConfigurationAdmin.SERVICE_FACTORYPID, getFactoryPidString() );

        // bundle location is not set here
        if ( withBundleLocation )
        {
            replaceProperty( properties, ConfigurationAdmin.SERVICE_BUNDLELOCATION, getStaticBundleLocation() );
        }
        else
        {
            properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
        }
        properties.remove( PROPERTY_LOCKED );
        properties.remove( PROPERTY_REVISION );
    }


    static void setAutoProperties( Dictionary<String, Object> properties, String pid, String factoryPid )
    {
        replaceProperty( properties, Constants.SERVICE_PID, pid );
        replaceProperty( properties, ConfigurationAdmin.SERVICE_FACTORYPID, factoryPid );
        properties.remove( ConfigurationAdmin.SERVICE_BUNDLELOCATION );
        properties.remove( PROPERTY_LOCKED );
        properties.remove( PROPERTY_REVISION );
    }


    private static final String[] AUTO_PROPS = new String[] {
            Constants.SERVICE_PID,
            ConfigurationAdmin.SERVICE_FACTORYPID,
            ConfigurationAdmin.SERVICE_BUNDLELOCATION,
            PROPERTY_LOCKED, PROPERTY_REVISION
    };

    static void clearAutoProperties( Dictionary<String, Object> properties )
    {
        for(final String p : AUTO_PROPS)
        {
            properties.remove( p );
        }
    }


    public void setLocked(final boolean flag) throws IOException
    {
        this.locked = flag;
        store();
    }

    /**
     * Compare the two properties, ignoring auto properties
     * @param props1 Set of properties
     * @param props2 Set of properties
     * @return {@code true} if the set of properties is equal
     */
    static boolean equals( Dictionary<String, Object> props1, Dictionary<String, Object> props2)
    {
        if (props1 == null) {
            if (props2 == null) {
                return true;
            } else {
                return false;
            }
        } else if (props2 == null) {
            return false;
        }

        final int count1 = getCount(props1);
        final int count2 = getCount(props2);
        if ( count1 != count2 )
        {
            return false;
        }

        final Enumeration<String> keys = props1.keys();
        while ( keys.hasMoreElements() )
        {
            final String key = keys.nextElement();
            if ( !isAutoProp(key) )
            {
                final Object val1 = props1.get(key);
                final Object val2 = props2.get(key);
                if ( val1 == null )
                {
                    if ( val2 != null )
                    {
                        return false;
                    }
                }
                else
                {
                    if ( val2 == null )
                    {
                        return false;
                    }
                    // arrays are compared using Arrays.equals
                    if ( val1.getClass().isArray() )
                    {
                        if ( !val2.getClass().isArray() )
                        {
                            return false;
                        }
                        final Object[] a1 = convertToObjectArray(val1);
                        final Object[] a2 = convertToObjectArray(val2);
                        if ( ! Arrays.equals(a1, a2) )
                        {
                            return false;
                        }
                    }
                    else if ( !val1.equals(val2) )
                    {
                        return false;
                    }
                }
            }
        }

        return true;
    }

    /**
     * Convert the object to an array
     * @param value The array
     * @return an object array
     */
    private static Object[] convertToObjectArray(final Object value)
    {
        final Object[] values;
        if (value instanceof long[])
        {
            final long[] a = (long[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof int[]) {
            final int[] a = (int[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        } else if (value instanceof double[])
        {
            final double[] a = (double[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof byte[])
        {
            final byte[] a = (byte[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof float[])
        {
            final float[] a = (float[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof short[])
        {
            final short[] a = (short[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof boolean[])
        {
            final boolean[] a = (boolean[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else if (value instanceof char[])
        {
            final char[] a = (char[])value;
            values = new Object[a.length];
            for(int i=0;i<a.length;i++)
            {
                values[i] = a[i];
            }
        }
        else
        {
            values = (Object[]) value;
        }
        return values;
    }

    static boolean isAutoProp(final String name)
    {
        for(final String p : AUTO_PROPS)
        {
            if ( p.equals(name) )
            {
                return true;
            }
        }
        return false;
    }

    static int getCount( Dictionary<String, Object> props )
    {
        int count = (props == null ? 0 : props.size());
        if ( props != null )
        {
            for(final String p : AUTO_PROPS)
            {
                if ( props.get(p) != null )
                {
                    count--;
                }
            }
        }
        return count;
    }

    public boolean isLocked()
    {
        return this.locked;
    }


    final ConfigurationManager getConfigurationManager()
    {
        return this.configurationManager;
    }
}
