/*
 * 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.ipojo.composite.instance;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.ConfigurationException;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.InstanceManager;
import org.apache.felix.ipojo.InstanceStateListener;
import org.apache.felix.ipojo.MissingHandlerException;
import org.apache.felix.ipojo.ServiceContext;
import org.apache.felix.ipojo.UnacceptableConfiguration;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.composite.CompositeHandler;
import org.apache.felix.ipojo.metadata.Element;
import org.apache.felix.ipojo.parser.ParseException;

/**
 * Composite Instance Handler.
 * This handler allows creating an instance inside a composite.
 * This instance is determine by its type and a configuration.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class InstanceHandler extends CompositeHandler implements InstanceStateListener {

    /**
     * Internal context.
     */
    private ServiceContext m_scope;

    /**
     * Available factories.
     */
    private Factory[] m_factories;

    /**
     * Handler description.
     */
    private InstanceHandlerDescription m_description;


    /**
     * This structure aims to manage a configuration. It stores all necessary
     * information to create an instance and to track the factory.
     */
    class ManagedConfiguration {
        /**
         * Configuration of the instance to create.
         */
        private Dictionary m_configuration;

        /**
         * Factory name.
         */
        private String m_factoryName;

        /**
         * Created instance.
         */
        private ComponentInstance m_instance;

        /**
         * Desired Factory (can be the classname).
         */
        private String m_desiredFactory;

        /**
         * Constructor.
         *
         * @param conf : the configuration to create.
         */
        ManagedConfiguration(Dictionary conf) {
            m_configuration = conf;
            m_desiredFactory = (String) conf.get("component");
        }

        /**
         * Return the managed configuration.
         * @return the configuration.
         */
        protected Dictionary getConfiguration() {
            return m_configuration;
        }

        /**
         * Return the used factory name.
         * @return the factory name
         */
        protected String getFactory() {
            return m_factoryName;
        }

        protected String getNeededFactoryName() {
            return m_desiredFactory;
        }

        /**
         * Return the created instance.
         * @return the instance (or null if no instance are created).
         */
        protected ComponentInstance getInstance() {
            return m_instance;
        }

        /**
         * Set the factory name.
         *
         * @param name : the factory name.
         */
        protected void setFactory(String name) {
            m_factoryName = name;
        }

        /**
         * Set the instance object.
         *
         * @param instance : the instance
         */
        protected void setInstance(ComponentInstance instance) {
            m_instance = instance;
        }
    }

    /**
     * Configurations to create and maintains.
     */
    private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];

    /**
     * Create an instance using the given factory and the given configuration.
     *
     * @param fact : the factory name to used.
     * @param config : the configuration.
     */
    private void createInstance(Factory fact, ManagedConfiguration config) {
        Dictionary conf = config.getConfiguration();
        try {
            config.setInstance(fact.createComponentInstance(conf, m_scope));
            config.setFactory(fact.getName());
            config.getInstance().addInstanceStateListener(this);
        } catch (UnacceptableConfiguration e) {
            error("A factory is available for the configuration but the configuration is not acceptable", e);
        } catch (MissingHandlerException e) {
            error("The instance creation has failed, at least one handler is missing", e);
        } catch (ConfigurationException e) {
            error("The instance creation has failed, an error during the configuration has occured", e);
        }
    }

    /**
     * A new valid factory appears.
     * @param factory : factory.
     */
    public void bindFactory(Factory factory) {
        boolean implicated = false;
        String factName = factory.getName();
        String className = factory.getComponentDescription().getClassName();
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() == null
                    && (m_configurations[i].getNeededFactoryName().equals(factName)
                            || m_configurations[i].getNeededFactoryName().equals(className))) {
                createInstance(factory, m_configurations[i]);
                implicated = true;
            }
        }
        if (implicated && ! getValidity()) {
            checkValidity();
        }
    }

    /**
     * An existing factory disappears or becomes invalid.
     * @param factory : factory
     */
    public void unbindFactory(Factory factory) {
        boolean implicated = false;
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factory.getName())) {
                m_configurations[i].setInstance(null);
                m_configurations[i].setFactory(null);
                implicated = true;
            }
        }
        if (implicated && getValidity()) {
            checkValidity();
        }
    }

    /**
     * Stop all created instances.
     */
    public synchronized void stop() {
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() != null) {
                m_configurations[i].getInstance().removeInstanceStateListener(this);
                if (m_configurations[i].getInstance().getState() != ComponentInstance.DISPOSED) {
                    m_configurations[i].getInstance().dispose();
                }
            }
            m_configurations[i].setInstance(null);
            m_configurations[i].setFactory(null);
        }
        m_configurations = new ManagedConfiguration[0];
    }

    /**
     * Configure method.
     * @param metadata : component type metadata.
     * @param configuration : instance configuration.
     * @throws ConfigurationException : occurs an instance cannot be parsed correctly.
     * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
     */
    public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
        m_scope = getCompositeManager().getServiceContext();

        // Prepare the configuration to append.
        Properties toAppend = new Properties();
        Enumeration keys = configuration.keys();
        while(keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            if (! (key.equals("instance.name")
                    || key.equals("component"))) { // Remove instance.name and component
                toAppend.put(key, configuration.get(key));
            }
        }

        Element[] instances = metadata.getElements("instance");
        m_configurations = new ManagedConfiguration[instances.length];
        for (int i = 0; i < instances.length; i++) {
            Properties conf = null;
            try {
                conf = parseInstance(instances[i]);
            } catch (ParseException e) {
                error("An instance cannot be parsed correctly", e);
                throw new ConfigurationException("An instance cannot be parsed correctly : " + e.getMessage());
            }

            Properties instanceConfiguration = new Properties();
            instanceConfiguration.putAll(conf);
            instanceConfiguration.putAll(toAppend);
            m_configurations[i] = new ManagedConfiguration(instanceConfiguration);
        }

        m_description = new InstanceHandlerDescription(this, m_configurations);
    }

    /**
     * Parse an Element to get a dictionary.
     * @param instance : the Element describing an instance.
     * @return : the resulting dictionary
     * @throws ParseException : occurs when a configuration cannot be parse correctly.
     */
    public static Properties parseInstance(Element instance) throws ParseException {
        Properties dict = new Properties();
        String name = instance.getAttribute("name");
        if (name != null) {
            dict.put("instance.name", name);
        }

        String comp = instance.getAttribute("component");
        if (comp == null) {
            throw new ParseException("An instance does not have the 'component' attribute");
        } else {
            dict.put("component", comp);
        }

        Element[] props = instance.getElements("property");
        for (int i = 0; props != null && i < props.length; i++) {
            parseProperty(props[i], dict);
        }

        return dict;
    }

    /**
     * Parse a property.
     * @param prop : the current element to parse
     * @param dict : the dictionary to populate
     * @throws ParseException : occurs if the property cannot be parsed correctly
     */
    public static void parseProperty(Element prop, Dictionary dict) throws ParseException {
        // Check that the property has a name
        String name = prop.getAttribute("name");
        String value = prop.getAttribute("value");
        if (name == null) { throw new ParseException("A property does not have the 'name' attribute"); }
        // Final case : the property element has a 'value' attribute
        if (value == null) {
            // Recursive case
            // Check if there is 'property' element
            Element[] subProps = prop.getElements("property");
            if (subProps == null) { throw new ParseException("A complex property must have at least one 'property' sub-element"); }
            Dictionary dict2 = new Properties();
            for (int i = 0; i < subProps.length; i++) {
                parseProperty(subProps[i], dict2);
                dict.put(prop.getAttribute("name"), dict2);
            }
        } else {
            dict.put(name, value);
        }
    }

    /**
     * Start method.
     * @see org.apache.felix.ipojo.Handler#start()
     */
    public void start() {
        for (int j = 0; j < m_factories.length; j++) {
            String factName = m_factories[j].getName();
            String className = m_factories[j].getClassName();
            for (int i = 0; i < m_configurations.length; i++) {
                if (m_configurations[i].getInstance() == null && (m_configurations[i].getNeededFactoryName().equals(factName) || m_configurations[i].getNeededFactoryName().equals(className))) {
                    createInstance(m_factories[j], m_configurations[i]);
                }
            }
        }
        checkValidity();
    }

    /**
     * Check handler validity.
     * The method update the validaity of the handler.
     */
    private void checkValidity() {
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() == null || m_configurations[i].getInstance().getState() != ComponentInstance.VALID) {
                setValidity(false);
                return;
            }
        }
        setValidity(true);
    }

    /**
     *  Instance state listener.
     *  This method listens when managed instance states change.
     *  @param instance : instance
     *  @param newState : the now state of the given instance
     *  @see org.apache.felix.ipojo.InstanceStateListener#stateChanged(org.apache.felix.ipojo.ComponentInstance, int)
     */
    public void stateChanged(ComponentInstance instance, int newState) {
        switch (newState) {
            case ComponentInstance.DISPOSED:
            case ComponentInstance.STOPPED:
                break; // Should not happen
            case ComponentInstance.VALID:
                if (!getValidity()) {
                    checkValidity();
                }
                break;
            case ComponentInstance.INVALID:
                if (getValidity()) {
                    checkValidity();
                }
                break;
            default:
                break;

        }
    }

    /**
     * Method returning an instance object of the given component type.
     * This method must be called only on 'primitive' type.
     * @param type : type.
     * @return an instance object or null if not found.
     */
    public Object getObjectFromInstance(String type) {
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() != null && type.equals(m_configurations[i].getFactory())) {
                if (m_configurations[i].getInstance().getState() == ComponentInstance.VALID) {
                    return ((InstanceManager) m_configurations[i].getInstance()).getPojoObject();
                } else {
                    error("An object cannot be get from the instance of the type " + type + ": invalid instance" + m_configurations[i].getInstance().getInstanceDescription().getDescription());
                    return null;
                }
            }
        }
        return null;
    }

    /**
     * Return the handler description, i.e. the state of created instances.
     * @return the handler description.
     * @see org.apache.felix.ipojo.Handler#getDescription()
     */
    public HandlerDescription getDescription() {
        return m_description;
    }

    /**
     * Get the list of used component type.
     * @return the list containing the used component type
     */
    public List getUsedType() {
        List result = new ArrayList();
        for (int i = 0; i < m_configurations.length; i++) {
            result.add(m_configurations[i].getConfiguration().get("component"));
        }
        return result;
    }

    /**
     * The composite is reconfigured, we check if we have a property to change.
     * We reconfigure all contained instances.
     * @param configuration the new instance configuration
     */
    public void reconfigure(Dictionary configuration) {
        for (int i = 0; i < m_configurations.length; i++) {
            if (m_configurations[i].getInstance() != null) {
                info("Reconfiguring " + m_configurations[i].getInstance().getInstanceName());
                m_configurations[i].getInstance().reconfigure(configuration);
            }
        }

    }
}
