/*
 * 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.aries.blueprint.container;

import java.util.*;
import java.util.concurrent.Callable;

import org.apache.aries.blueprint.ExtendedBlueprintContainer;
import org.apache.aries.blueprint.ExtendedReferenceListMetadata;
import org.apache.aries.blueprint.ExtendedServiceReferenceMetadata;
import org.apache.aries.blueprint.di.Recipe;
import org.apache.aries.blueprint.di.CollectionRecipe;
import org.apache.aries.blueprint.utils.DynamicCollection;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.blueprint.container.ReifiedType;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.container.ServiceUnavailableException;
import org.osgi.service.blueprint.reflect.ReferenceListMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A recipe to create a managed collection of service references
 *
 * @version $Rev$, $Date$
 */
public class ReferenceListRecipe extends AbstractServiceReferenceRecipe {

    private static final Logger LOGGER = LoggerFactory.getLogger(ReferenceListRecipe.class);

    private final ReferenceListMetadata metadata;
    private final List<ManagedCollection> collections = new ArrayList<ManagedCollection>();
    private final DynamicCollection<ServiceDispatcher> storage = new DynamicCollection<ServiceDispatcher>();
    private final List<ServiceDispatcher> unboundDispatchers = new ArrayList<ServiceDispatcher>();
    private final Object monitor = new Object();
    
    public ReferenceListRecipe(String name,
                         ExtendedBlueprintContainer blueprintContainer,
                         ReferenceListMetadata metadata,
                         CollectionRecipe listenersRecipe,
                         List<Recipe> explicitDependencies) {
        super(name, blueprintContainer, metadata, listenersRecipe, explicitDependencies);
        this.metadata = metadata;
    }

    @Override
    protected Object internalCreate() throws ComponentDefinitionException {
        try {
            if (explicitDependencies != null) {
                for (Recipe recipe : explicitDependencies) {
                    recipe.create();
                }
            }
            ProvidedObject object = new ProvidedObject();
            addPartialObject(object);
            // Handle initial references
            createListeners();
            updateListeners();
           
            return object;
        } catch (ComponentDefinitionException t) {
            throw t;
        } catch (Throwable t) {
            throw new ComponentDefinitionException(t);
        }
    }

    protected void retrack() {
        List<ServiceReference> refs = getServiceReferences();
        if (refs != null) {
            for (ServiceReference ref : refs) {
                track(ref);
            }
        }
    }

    protected void track(ServiceReference reference) {
        synchronized (monitor) {
            try {
                // ServiceReferences may be tracked at multiple points:
                //  * first after the collection creation in #internalCreate()
                //  * in #postCreate() after listeners are created
                //  * after creation time if a new reference shows up
                //
                // In the first step, listeners are not created, so we add
                // the dispatcher to the unboundDispatchers list.  In the second
                // step, the dispatcher has already been added to the collection
                // so we just call the listener.
                //
                ServiceDispatcher dispatcher = findDispatcher(reference);
                if (dispatcher != null) {
                    if (!unboundDispatchers.remove(dispatcher)) {
                        return;
                    }
                } else {
                    dispatcher = new ServiceDispatcher(reference);
                    Set<Class> interfaces = new HashSet<Class>();
                    if (metadata.getInterface() != null) {
                        interfaces.add(loadClass(metadata.getInterface()));
                    }
                    if (metadata instanceof ExtendedReferenceListMetadata) {
                        if (((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface() != null) {
                            interfaces.add(((ExtendedServiceReferenceMetadata) metadata).getRuntimeInterface());
                        }
                        boolean greedy = (((ExtendedReferenceListMetadata) metadata).getProxyMethod() & ExtendedReferenceListMetadata.PROXY_METHOD_GREEDY) != 0;
                        if (greedy) {
                            List<String> ifs = Arrays.asList((String[]) reference.getProperty(Constants.OBJECTCLASS));
                            interfaces.addAll(loadAllClasses(ifs));
                        }
                    }
                    dispatcher.proxy = createProxy(dispatcher, interfaces);
                    if (!storage.add(dispatcher)) {
                        dispatcher.destroy();
                        return;
                    }
                }
                if (listeners != null) {
                    bind(dispatcher.reference, dispatcher.proxy);                   
                } else {
                    unboundDispatchers.add(dispatcher);
                }
            } catch (Throwable t) {
                LOGGER.info("Error tracking new service reference", t);
            }
        }
    }

    protected void untrack(ServiceReference reference) {
        synchronized (monitor) {
            ServiceDispatcher dispatcher = findDispatcher(reference);
            if (dispatcher != null) {
                unbind(dispatcher.reference, dispatcher.proxy);
                storage.remove(dispatcher);
                dispatcher.destroy();
            }
        }
    }

    protected ServiceDispatcher findDispatcher(ServiceReference reference) {
        for (ServiceDispatcher dispatcher : storage) {
            if (dispatcher.reference == reference) {
                return dispatcher;
            }
        }
        return null;
    }

    protected ManagedCollection getManagedCollection(boolean useReferences) {
        for (ManagedCollection col : collections) {
            if (col.references == useReferences) {
                return col;
            }
        }
        ManagedCollection collection = new ManagedCollection(useReferences, storage);
        collections.add(collection);
        return collection;
    }

    /**
     * The ServiceDispatcher is used when creating the cglib proxy.
     * Thic class is responsible for getting the actual service that will be used.
     */
    public class ServiceDispatcher implements Callable<Object> {

        public ServiceReference reference;
        public Object service;
        public Object proxy;
        
        public ServiceDispatcher(ServiceReference reference) throws Exception {
            this.reference = reference;
        }

        public synchronized void destroy() {
            if (reference != null) {
                reference.getBundle().getBundleContext().ungetService(reference);
                reference = null;
                service = null;
                proxy = null;
            }
        }

        public synchronized Object call() throws Exception {
            if (reference == null) {
                throw new ServiceUnavailableException("Service is unavailable", getOsgiFilter());
            }
            if (service == null) {
                service = blueprintContainer.getService(reference);
            }
            return service;
        }

    }

    public class ProvidedObject implements AggregateConverter.Convertible {

        public Object convert(ReifiedType type) {
            LOGGER.debug("Converting ManagedCollection to {}", type);
            if (!type.getRawClass().isAssignableFrom(List.class)) {
                throw new ComponentDefinitionException("<reference-list/> can only be converted to a List, not " + type);
            }
            int memberType = metadata.getMemberType();            
            boolean useRef = false;
            if (type.size() == 1) {
                useRef = (type.getActualTypeArgument(0).getRawClass() == ServiceReference.class);
                if ( (useRef && memberType == ReferenceListMetadata.USE_SERVICE_OBJECT) ||
                     (!useRef && memberType == ReferenceListMetadata.USE_SERVICE_REFERENCE)) {
                    throw new ComponentDefinitionException("The memeber-type specified is incompatible with generic injection type");
                }
            }
            boolean references;
            if (memberType == ReferenceListMetadata.USE_SERVICE_REFERENCE) {                
                references = true;
            } else if (memberType == ReferenceListMetadata.USE_SERVICE_OBJECT) {
                references = false;
            } else {
                references = useRef;
            }
            LOGGER.debug("ManagedCollection references={}", references);
            return getManagedCollection(references);
        }

    }

    /**
     * Base class for managed collections.
     *
     * TODO: list iterators should not be supported
     * TODO: rework the iteration so that if hasNext() has returned false, it will always return false
     * TODO: implement subList()
     */
    public static class ManagedCollection extends AbstractCollection implements List, RandomAccess {

        protected final DynamicCollection<ServiceDispatcher> dispatchers;
        protected boolean references;

        public ManagedCollection(boolean references, DynamicCollection<ServiceDispatcher> dispatchers) {
            this.references = references;
            this.dispatchers = dispatchers;
            LOGGER.debug("ManagedCollection references={}", references);
        }

        public boolean addDispatcher(ServiceDispatcher dispatcher) {
            return dispatchers.add(dispatcher);
        }

        public boolean removeDispatcher(ServiceDispatcher dispatcher) {
            return dispatchers.remove(dispatcher);
        }

        public DynamicCollection<ServiceDispatcher> getDispatchers() {
            return dispatchers;
        }

        public Iterator iterator() {
            return new ManagedListIterator(dispatchers.iterator());
        }

        public int size() {
            return dispatchers.size();
        }

        @Override
        public boolean add(Object o) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        @Override
        public boolean remove(Object o) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        @Override
        public boolean addAll(Collection c) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        @Override
        public void clear() {
            throw new UnsupportedOperationException("This collection is read only");
        }

        @Override
        public boolean retainAll(Collection c) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        @Override
        public boolean removeAll(Collection c) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        public Object get(int index) {
            return references ? dispatchers.get(index).reference : dispatchers.get(index).proxy;
        }

        public int indexOf(Object o) {
            if (o == null) {
                throw new NullPointerException();
            }
            ListIterator e = listIterator();
            while (e.hasNext()) {
                if (o.equals(e.next())) {
                    return e.previousIndex();
                }
            }
            return -1;
        }

        public int lastIndexOf(Object o) {
            if (o == null) {
                throw new NullPointerException();
            }
            ListIterator e = listIterator(size());
            while (e.hasPrevious()) {
                if (o.equals(e.previous())) {
                    return e.nextIndex();
                }
            }
            return -1;
        }

        public ListIterator listIterator() {
            return listIterator(0);
        }

        public ListIterator listIterator(int index) {
            return new ManagedListIterator(dispatchers.iterator(index));
        }

        public List<ServiceDispatcher> subList(int fromIndex, int toIndex) {
            throw new UnsupportedOperationException("Not implemented");
        }

        public Object set(int index, Object element) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        public void add(int index, Object element) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        public Object remove(int index) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        public boolean addAll(int index, Collection c) {
            throw new UnsupportedOperationException("This collection is read only");
        }

        public class ManagedListIterator implements ListIterator {

            protected final ListIterator<ServiceDispatcher> iterator;

            public ManagedListIterator(ListIterator<ServiceDispatcher> iterator) {
                this.iterator = iterator;
            }

            public boolean hasNext() {
                return iterator.hasNext();
            }

            public Object next() {
                return references ? iterator.next().reference : iterator.next().proxy;
            }

            public boolean hasPrevious() {
                return iterator.hasPrevious();
            }

            public Object previous() {
                return references ? iterator.previous().reference : iterator.previous().proxy;
            }

            public int nextIndex() {
                return iterator.nextIndex();
            }

            public int previousIndex() {
                return iterator.previousIndex();
            }

            public void remove() {
                throw new UnsupportedOperationException("This collection is read only");
            }

            public void set(Object o) {
                throw new UnsupportedOperationException("This collection is read only");
            }

            public void add(Object o) {
                throw new UnsupportedOperationException("This collection is read only");
            }
        }

    }


}
