/* 
 * 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.service.instantiator;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.List;
import java.util.Properties;

import org.apache.felix.ipojo.PolicyServiceContext;
import org.apache.felix.ipojo.util.DependencyModel;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;

/**
 * Import a service form the parent to the internal service registry.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
public class ServiceImporter extends DependencyModel {

    /**
     * Reference on the handler.
     */
    private ServiceDependencyHandler m_handler;

    private final class Record {
        /**
         * External Reference.
         */
        private ServiceReference m_ref;

        /**
         * Internal Registration.
         */
        private ServiceRegistration m_reg;

        /**
         * Exposed Object.
         */
        private Object m_svcObject;

        /**
         * Constructor.
         * @param ref : service reference.
         */
        protected Record(ServiceReference ref) {
            m_ref = ref;
        }

        /**
         * Register the current import.
         */
        private void register() {
            if (m_reg != null) {
                m_reg.unregister();
            }
            m_svcObject = getService(m_ref);
            m_reg = m_handler.getCompositeManager().getServiceContext()
                .registerService(getSpecification().getName(), m_svcObject, getProps(m_ref));
        }

        /**
         * Update the current import.
         */
        private void update() {
            if (m_reg != null) {
                m_reg.setProperties(getProps(m_ref));
            }
        }

        /**
         * Unregister and release the current import.
         */
        private void dispose() {
            if (m_reg != null) {
                m_reg.unregister();
                m_svcObject = null;
                m_reg = null;
            }
            m_ref = null;
        }

        /**
         * Test object equality.
         * @param object : object to confront against the current object.
         * @return true if the two objects are equals (same service reference).
         * @see java.lang.Object#equals(java.lang.Object)
         */
        public boolean equals(Object object) {
            if (object instanceof Record) {
                Record rec = (Record) object;
                return rec.m_ref == m_ref;
            }
            return false;
        }
        
        /**
         * Hash code method.
         * @return the hash code by calling the parent method.
         */
        public int hashCode() {
            return super.hashCode();
        }
    }

    /**
     * List of managed records.
     */
    private List/*<Record>*/m_records = new ArrayList()/* <Record> */;

    /**
     * Requirement Id.
     */
    private String m_id;

    /**
     * Is this requirement attached to a service-level requirement.
     */
    private boolean m_specLevelReq;

    /**
     * Is the set of used provider frozen ?
     */
    private boolean m_isFrozen;

    /**
     * Constructor.
     * 
     * @param specification : targeted specification
     * @param filter : LDAP filter
     * @param multiple : should the importer imports several services ?
     * @param optional : is the import optional ?
     * @param cmp : comparator to use for the tracking 
     * @param policy : resolving policy
     * @param context : bundle context to use for the tracking (can be a servie context)
     * @param identitity : requirement id (may be null)
     * @param handler : handler
     */
    public ServiceImporter(Class specification, Filter filter, boolean multiple, boolean optional, Comparator cmp, int policy, BundleContext context, String identitity
            , ServiceDependencyHandler handler) {
        super(specification, multiple, optional, filter, cmp, policy, context, handler, handler.getCompositeManager());

        this.m_handler = handler;

        if (m_id == null) {
            m_id = super.getSpecification().getName();
        } else {
            m_id = identitity;
        }

    }

    /**
     * Get the properties for the exposed service from the given reference.
     * 
     * @param ref : the reference.
     * @return the property dictionary
     */
    private static Dictionary getProps(ServiceReference ref) {
        Properties prop = new Properties();
        String[] keys = ref.getPropertyKeys();
        for (int i = 0; i < keys.length; i++) {
            prop.put(keys[i], ref.getProperty(keys[i]));
        }
        return prop;
    }

    /**
     * Freeze the set of used provider.
     * This method allow to fix the set of provider when the static binding policy is used.
     */
    public void freeze() {
        m_isFrozen = true;
    }
    
    /**
     * Unfreezes.
     */
    public void unfreeze() {
        m_isFrozen = false;
    }

    public boolean isFrozen() {
        return m_isFrozen;
    }

    /**
     * Stop the management of the import.
     */
    public void stop() {

        super.stop();

        for (int i = 0; i < m_records.size(); i++) {
            Record rec = (Record) m_records.get(i);
            rec.dispose();
        }

        m_records.clear();

    }

    /**
     * Get the record list using the given reference.
     * 
     * @param ref : the reference
     * @return the list containing all record using the given reference
     */
    private List/* <Record> */getRecordsByRef(ServiceReference ref) {
        List list = new ArrayList();
        for (int i = 0; i < m_records.size(); i++) {
            Record rec = (Record) m_records.get(i);
            if (rec.m_ref == ref) {
                list.add(rec);
            }
        }
        return list;
    }

    /**
     * Build the list of imported service provider.
     * @return the list of all imported services.
     */
    public List getProviders() {
        List list = new ArrayList();
        for (int i = 0; i < m_records.size(); i++) {
            list.add((((Record) m_records.get(i)).m_ref).getProperty("instance.name"));
        }
        return list;
    }

    /**
     * Set that this dependency is a service level dependency.
     * This forces the scoping policy to be STRICT.
     */
    public void setServiceLevelDependency() {
        m_specLevelReq = true;
        PolicyServiceContext context = new PolicyServiceContext(m_handler.getCompositeManager().getGlobalContext(), m_handler.getCompositeManager().getParentServiceContext(), PolicyServiceContext.LOCAL);
        setBundleContext(context);
    }

    public String getId() {
        return m_id;
    }

    public boolean isServiceLevelRequirement() {
        return m_specLevelReq;
    }

    /**
     * On Dependency Reconfiguration notification method.
     * @param departs : leaving service references.
     * @param arrivals : new injected service references.
     * @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[])
     */
    public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) {
        for (int i = 0; departs != null && i < departs.length; i++) {
            onServiceDeparture(departs[i]);
        }
        
        for (int i = 0; arrivals != null && i < arrivals.length; i++) {
            onServiceArrival(arrivals[i]);
        }
    }

    /**
     * A new service is injected by the tracker.
     * This method create a 'Record' and register it.
     * @param ref : new service reference.
     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceArrival(org.osgi.framework.ServiceReference)
     */
    public void onServiceArrival(ServiceReference ref) {
        Record rec = new Record(ref);
        m_records.add(rec);
        // Always register the reference, as the method is call only when needed. 
        rec.register();
    }

    /**
     * A used service disappears.
     * This method find the implicated 'Record', dispose it and remove it from the list.
     * @param ref : leaving service reference.
     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceDeparture(org.osgi.framework.ServiceReference)
     */
    public void onServiceDeparture(ServiceReference ref) {
        List list = getRecordsByRef(ref);
        for (int i = 0; i < list.size(); i++) { // Stop the implied record
            Record rec = (Record) list.get(i);
            rec.dispose();
        }
        m_records.removeAll(list);
    }

    /**
     * A used service is modified.
     * @param ref : modified service reference.
     * @see org.apache.felix.ipojo.util.DependencyModel#onServiceModification(org.osgi.framework.ServiceReference)
     */
    public void onServiceModification(ServiceReference ref) {
        List list = getRecordsByRef(ref);
        for (int i = 0; i < list.size(); i++) { // Stop the implied record
            Record rec = (Record) list.get(i);
            rec.update();
        }
    }

}
