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

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import org.apache.felix.scr.component.ExtFactoryComponentInstance;
import org.apache.felix.scr.impl.BundleComponentActivator;
import org.apache.felix.scr.impl.inject.ComponentMethods;
import org.apache.felix.scr.impl.inject.RefPair;
import org.apache.felix.scr.impl.logger.InternalLogger.Level;
import org.apache.felix.scr.impl.metadata.ComponentMetadata;
import org.apache.felix.scr.impl.metadata.ReferenceMetadata;
import org.apache.felix.scr.impl.metadata.TargetedPID;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentConstants;
import org.osgi.service.component.ComponentException;
import org.osgi.service.component.ComponentFactory;
import org.osgi.service.component.ComponentInstance;

/**
 * The <code>ComponentFactoryImpl</code> extends the {@link AbstractComponentManager}
 * class to implement the component factory functionality. As such the
 * OSGi Declarative Services <code>ComponentFactory</code> interface is
 * implemented.
 * <p>
 * In addition the {@link ComponentHolder} interface is implemented to use this
 * class directly as the holder for component instances created by the
 * {@link #newInstance(Dictionary)} method.
 * <p>
 * This class implements spec-compliant component factories and the felix
 * "persistent" component factory, where the factory is always registered whether or
 * not all dependencies are present and the created components also persist whether or
 * not the dependencies are present to allow the component instance to exist.
 */
public class ComponentFactoryImpl<S> extends AbstractComponentManager<S> implements ComponentFactory<S>, ComponentContainer<S>
{

    /**
     * Contains the component instances created by calling the
     * {@link #newInstance(Dictionary)} method. These component instances are
     * provided with updated configuration (or deleted configuration) if
     * such modifications for the component factory takes place.
     * <p>
     * The map is keyed by the component manager instances. The value of each
     * entry is the same as the entry's key.
     * This is an IdentityHashMap for speed, thus not a Set.
     */
    private final Map<SingleComponentManager<S>, SingleComponentManager<S>> m_componentInstances;

    /**
     * The configuration for the component factory. This configuration is
     * supplied as the base configuration for each component instance created
     * by the {@link #newInstance(Dictionary)} method.
     */
    private volatile Map<String, Object> m_configuration;

    /**
     * Flag telling if our component factory is currently configured from config admin.
     * We are configured when configuration policy is required and we have received the
     * config admin properties, or when configuration policy is optional or ignored.
     */
    private volatile boolean m_hasConfiguration;

    /**
     * Configuration change count (R5) or imitation (R4)
     */
    protected volatile long m_changeCount = -1;

    protected TargetedPID m_targetedPID;

    public ComponentFactoryImpl( ComponentContainer<S> container, ComponentMethods componentMethods )
    {
        super( container, componentMethods );
        m_componentInstances = new IdentityHashMap<>();
        m_configuration = new HashMap<>();
    }


    @Override
    protected boolean verifyDependencyManagers()
    {
        if (!getComponentMetadata().isPersistentFactoryComponent())
        {
            return super.verifyDependencyManagers();
        }
        return true;
    }

    @Override
    public boolean isFactory()
    {
        return true;
    }

    /* (non-Javadoc)
    * @see org.osgi.service.component.ComponentFactory#newInstance(java.util.Dictionary)
    */
    @Override
    public ComponentInstance<S> newInstance( Dictionary<String, ?> dictionary )
    {
        final SingleComponentManager<S> cm = createComponentManager();
        getLogger().log(Level.DEBUG, "Creating new instance from component factory",
            null);

        cm.setFactoryProperties( dictionary );
        //configure the properties
        cm.reconfigure( m_configuration, false, null );
        // enable
        cm.enableInternal();

        ComponentInstance<S> instance;
        if ( getComponentMetadata().isPersistentFactoryComponent() )
        {
            instance = new ModifyComponentInstance<>(cm);
        }
        else
        {
        	instance = cm.getComponentInstance();
        	if ( instance == null ||  instance.getInstance() == null )
        	{
        		// activation failed, clean up component manager
        		cm.dispose( ComponentConstants.DEACTIVATION_REASON_DISPOSED );
        		throw new ComponentException( "Failed activating component" );
        	}
        }

        synchronized ( m_componentInstances )
        {
            m_componentInstances.put( cm, cm );
        }

        return instance;
    }

    private static class ModifyComponentInstance<S> implements ExtFactoryComponentInstance<S>
    {
        private final SingleComponentManager<S> cm;

        public ModifyComponentInstance(SingleComponentManager<S> cm)
        {
            this.cm = cm;
        }

        @Override
        public void dispose()
        {
            cm.dispose();
        }

        @Override
        public S getInstance()
        {
            final ComponentInstance<S> componentInstance = cm.getComponentInstance();
            return componentInstance == null? null: componentInstance.getInstance();
        }

        @Override
        public void modify(Dictionary<String, ?> properties)
        {
            cm.setFactoryProperties( properties );
            cm.reconfigure(false);
        }

    }

    /**
     * Compares this {@code ComponentFactoryImpl} object to another object.
     *
     * <p>
     * A component factory impl is considered to be <b>equal to </b> another component
     * factory impl if the component names are equal(using {@code String.equals}).
     *
     * @param object The {@code ComponentFactoryImpl} object to be compared.
     * @return {@code true} if {@code object} is a
     *         {@code ComponentFactoryImpl} and is equal to this object;
     *         {@code false} otherwise.
     */
    @Override
    public boolean equals(Object object)
    {
        if (!(object instanceof ComponentFactoryImpl<?>))
        {
            return false;
        }

        ComponentFactoryImpl<?> other = (ComponentFactoryImpl<?>) object;
        return getComponentMetadata().getName().equals(other.getComponentMetadata().getName());
    }

   /**
    * Returns a hash code value for the object.
    *
    * @return An integer which is a hash code value for this object.
    */
   @Override
public int hashCode()
   {
       return getComponentMetadata().getName().hashCode();
   }

    /**
     * The component factory does not have a component to delete.
     * <p>
     * But in the backwards compatible case any instances created for factory
     * configuration instances are to disabled as a consequence of deactivating
     * the component factory.
     */
    @Override
    protected void deleteComponent( int reason )
    {
    }


    @Override
    protected String[] getProvidedServices()
    {
        return new String[] { ComponentFactory.class.getName() };
    }


    public boolean hasConfiguration()
    {
        return m_hasConfiguration;
    }


    /**
     * For ComponentFactoryImpl, this is used only for updating targets on the dependency managers, so we don't need any other
     * properties.
     */
    @Override
    public Map<String, Object> getProperties()
    {
        Map<String, Object> props = new HashMap<>();

        // add target properties of references
        List<ReferenceMetadata> depMetaData = getComponentMetadata().getDependencies();
        for ( ReferenceMetadata rm : depMetaData )
        {
            if ( rm.getTarget() != null )
            {
                props.put( rm.getTargetPropertyName(), rm.getTarget() );
            }
        }

        // add target properties from configuration (if we have one)
        for ( String key :  m_configuration.keySet() )
        {
            if ( key.endsWith( ".target" ) )
            {
                props.put( key, m_configuration.get( key ) );
            }
        }

        return props;
    }

    @Override
    public void setServiceProperties( Dictionary<String, ?> serviceProperties )
    {
        throw new IllegalStateException( "ComponentFactory service properties are immutable" );
    }

    @Override
    void postRegister()
    {
        //do nothing
    }

    @Override
    void preDeregister()
    {
        //do nothing
    }

    @Override
    public Dictionary<String, Object> getServiceProperties()
    {
        Dictionary<String, Object> props = new Hashtable<>(getComponentMetadata().getFactoryProperties());

        // 112.5.5 The Component Factory service must register with the following properties
        props.put( ComponentConstants.COMPONENT_NAME, getComponentMetadata().getName() );
        props.put( ComponentConstants.COMPONENT_FACTORY, getComponentMetadata().getFactoryIdentifier() );

        props.put( Constants.SERVICE_VENDOR, "The Apache Software Foundation" );

        return props;
    }

    @Override
    protected boolean collectDependencies(ComponentContextImpl<S> componentContext)
    {
        return true;
    }

    @Override
    <T> boolean invokeUpdatedMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> ref, int trackingCount )
    {
    	return false;
    }

    @Override
    <T> void invokeBindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> reference, int trackingCount )
    {
    }

    @Override
    <T> void invokeUnbindMethod( DependencyManager<S, T> dependencyManager, RefPair<S, T> oldRef, int trackingCount )
    {
    }

    //---------- Component interface


    /**
     * Disposes off all components ever created by this component holder. This
     * method is called if either the Declarative Services runtime is stopping
     * or if the owning bundle is stopped. In both cases all components created
     * by this holder must be disposed off.
     */
    @Override
    public void dispose( int reason )
    {
        List<AbstractComponentManager<S>> cms = new ArrayList<>( );
        getComponentManagers( m_componentInstances, cms );
        for ( AbstractComponentManager<S> acm: cms )
        {
            acm.dispose( reason );
        }

        synchronized ( m_componentInstances )
        {
            m_componentInstances.clear();
        }

        // finally dispose the component factory itself
        super.dispose( reason );
    }


    @Override
    public void disposed( SingleComponentManager<S> component )
    {
        synchronized ( m_componentInstances )
        {
            m_componentInstances.remove( component );
        }
    }


    //---------- internal


    /**
     * Creates an {@link SingleComponentManager} instance with the
     * {@link BundleComponentActivator} and {@link ComponentMetadata} of this
     * instance. The component manager is kept in the internal set of created
     * components. The component is neither configured nor enabled.
     */
    private SingleComponentManager<S> createComponentManager()
    {
        return new SingleComponentManager<>( this, getComponentMethods(), !getComponentMetadata().isPersistentFactoryComponent() );
    }


    protected void getComponentManagers( Map<?, SingleComponentManager<S>> componentMap, List<AbstractComponentManager<S>> componentManagers )
    {
        if ( componentMap != null )
        {
            synchronized ( componentMap )
            {
                componentManagers.addAll( componentMap.values() );
            }
        }
    }

    public TargetedPID getConfigurationTargetedPID(TargetedPID pid, TargetedPID factoryPid)
    {
        return m_targetedPID;
    }


	@Override
	public void reconfigure(Map<String, Object> configuration, boolean configurationDeleted, TargetedPID factoryPid) {
	    if ( factoryPid != null ) {
	        // ignore factory configuration changes for component factories.
	        return;
	    }
		m_configuration = configuration;
		List<SingleComponentManager<S>> cms;
		synchronized (m_componentInstances)
        {
            cms = new ArrayList<>(m_componentInstances.keySet());
        }
		for (SingleComponentManager<S> cm: cms)
		{
		    cm.reconfigure( configuration, configurationDeleted, factoryPid);
		}
	}


    @Override
    public void getComponentManagers(List<AbstractComponentManager<S>> cms)
    {
        synchronized (m_componentInstances)
        {
            cms.addAll(m_componentInstances.keySet());
        }
    }
}
