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

import java.io.File;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.felix.connect.felix.framework.HookRegistry;
import org.apache.felix.connect.felix.framework.ServiceRegistry;
import org.apache.felix.connect.felix.framework.capabilityset.SimpleFilter;
import org.apache.felix.connect.felix.framework.util.EventDispatcher;
import org.apache.felix.connect.felix.framework.util.ShrinkableCollection;
import org.apache.felix.connect.felix.framework.util.Util;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.hooks.service.FindHook;

class PojoSRBundleContext implements BundleContext
{
    private final Bundle m_bundle;
    private final ServiceRegistry m_reg;
    private final EventDispatcher m_dispatcher;
    private final Map<Long, Bundle> m_bundles;
    private final Map<String, Object> m_config;

    public PojoSRBundleContext(Bundle bundle, ServiceRegistry reg,
                               EventDispatcher dispatcher, Map<Long, Bundle> bundles, Map<String, Object> config)
    {
        m_bundle = bundle;
        m_reg = reg;
        m_dispatcher = dispatcher;
        m_bundles = bundles;
        m_config = config;
    }

    public boolean ungetService(ServiceReference reference)
    {
        return m_reg.ungetService(m_bundle, reference, null);
    }

    public void removeServiceListener(ServiceListener listener)
    {
        m_dispatcher.removeListener(this, ServiceListener.class,
                listener);
    }

    public void removeFrameworkListener(FrameworkListener listener)
    {
        m_dispatcher
                .removeListener(this, FrameworkListener.class, listener);
    }

    public void removeBundleListener(BundleListener listener)
    {
        m_dispatcher.removeListener(this, BundleListener.class, listener);
    }

    public ServiceRegistration registerService(String clazz, Object service,
                                               Dictionary properties)
    {
        return registerService(new String[]{clazz}, service, properties);
    }

    public ServiceRegistration registerService(String[] clazzes,
                                               Object service, Dictionary properties)
    {
        ServiceRegistration reg = m_reg.registerService(m_bundle, clazzes, service,
            properties);

        // Check to see if this a listener hook; if so, then we need
        // to invoke the callback with all existing service listeners.
        if (HookRegistry.isHook(
            clazzes, org.osgi.framework.hooks.service.ListenerHook.class, service))
        {
            org.osgi.framework.hooks.service.ListenerHook lh =
                (org.osgi.framework.hooks.service.ListenerHook)
                    m_reg.getService(m_bundle, reg.getReference(), false);

            if (lh != null)
            {
                try
                {
                    lh.added(m_dispatcher.getAllServiceListeners());
                }
                catch (Throwable th)
                {
                    System.out.println("Problem invoking service registry hook");
                    th.printStackTrace();
                }
                finally
                {
                    m_reg.ungetService(m_bundle, reg.getReference(), null);
                }
            }
        }

        m_dispatcher.fireServiceEvent(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()), null, m_bundles.get(0L));

        return reg;
    }

    public Bundle installBundle(String location) throws BundleException
    {
        throw new BundleException("pojosr can't do that");
    }

    public Bundle installBundle(String location, InputStream input)
            throws BundleException
    {

        throw new BundleException("pojosr can't do that");
    }

    public ServiceReference<?>[] getServiceReferences(String clazz, String filter)
            throws InvalidSyntaxException
    {
        return getServiceReferences(clazz, filter, true);
    }

    public ServiceReference<?> getServiceReference(String clazz)
    {
        try
        {
            return getBestServiceReference(getServiceReferences(clazz, null));
        }
        catch (InvalidSyntaxException e)
        {
            throw new IllegalStateException(e);
        }
    }

    private ServiceReference<?> getBestServiceReference(ServiceReference<?>[] refs)
    {
        if (refs == null)
        {
            return null;
        }

        if (refs.length == 1)
        {
            return refs[0];
        }

        // Loop through all service references and return
        // the "best" one according to its rank and ID.
        ServiceReference bestRef = refs[0];
        for (int i = 1; i < refs.length; i++)
        {
            if (bestRef.compareTo(refs[i]) < 0)
            {
                bestRef = refs[i];
            }
        }

        return bestRef;
    }

    public <S> S getService(ServiceReference<S> reference)
    {
        try 
        {
            return m_reg.getService(m_bundle, reference, false);
        } 
        catch ( ServiceException ex ) 
        {
            m_dispatcher.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.ERROR, m_bundle, ex));
        }
        return null;
    }

    @Override
    public <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference) {
        return new ServiceObjectsImpl<S>(reference);
    }


    //
    // ServiceObjects implementation
    //
    class ServiceObjectsImpl<S> implements ServiceObjects<S>
    {
        private final ServiceReference<S> m_ref;

        public ServiceObjectsImpl(final ServiceReference<S> ref)
        {
            this.m_ref = ref;
        }

        public S getService() {
            return m_reg.getService(m_bundle, m_ref, true);
        }

        public void ungetService(final S srvObj) {// Unget the specified service.
            if ( !m_reg.ungetService(m_bundle, m_ref, srvObj))
            {
                throw new IllegalArgumentException();
            }
        }

        public ServiceReference<S> getServiceReference()
        {
            return m_ref;
        }
    }
    public String getProperty(String key)
    {
        Object result = m_config.get(key);

        return result == null ? System.getProperty(key) : result.toString();
    }

    public File getDataFile(String filename)
    {
        File root = new File("bundle" + m_bundle.getBundleId());
        String storage = getProperty("org.osgi.framework.storage");
        if (storage != null)
        {
            root = new File(new File(storage), root.getName());
        }
        root.mkdirs();
        return filename.trim().length() > 0 ? new File(root, filename) : root;
    }

    public Bundle[] getBundles()
    {
        Bundle[] result = m_bundles.values().toArray(
                new Bundle[m_bundles.size()]);
        Arrays.sort(result, new Comparator<Bundle>()
        {

            public int compare(Bundle o1, Bundle o2)
            {
                return (int) (o1.getBundleId() - o2.getBundleId());
            }
        });
        return result;
    }

    public Bundle getBundle(long id)
    {
        return m_bundles.get(id);
    }

    public Bundle getBundle()
    {
        return m_bundle;
    }

    public ServiceReference[] getAllServiceReferences(String clazz,
                                                      String filter) throws InvalidSyntaxException
    {
        return getServiceReferences(clazz, filter, false);
    }

    /**
     * Retrieves an array of {@link ServiceReference} objects based on calling bundle,
     * service class name, and filter expression.  Optionally checks for isAssignable to
     * make sure that the service can be cast to the
     * @param className Service Classname or <code>null</code> for all
     * @param expr Filter Criteria or <code>null</code>
     * @return Array of ServiceReference objects that meet the criteria
     * @throws InvalidSyntaxException
     */
    ServiceReference[] getServiceReferences(
            final String className,
            final String expr, final boolean checkAssignable)
            throws InvalidSyntaxException
    {
        // Define filter if expression is not null.
        SimpleFilter filter = null;
        if (expr != null)
        {
            try
            {
                filter = SimpleFilter.parse(expr);
            }
            catch (Exception ex)
            {
                throw new InvalidSyntaxException(ex.getMessage(), expr);
            }
        }

        // Ask the service registry for all matching service references.
        final Collection<ServiceReference<?>> refList = (Collection) m_reg.getServiceReferences(className, filter);

        // Filter on assignable references
        if (checkAssignable)
        {
            for (Iterator it = refList.iterator(); it.hasNext();)
            {
                // Get the current service reference.
                ServiceReference ref = (ServiceReference) it.next();
                // Now check for castability.
                if (!Util.isServiceAssignable(m_bundle, ref))
                {
                    it.remove();
                }
            }
        }

        // activate findhooks
        Set<ServiceReference<FindHook>> findHooks = m_reg.getHookRegistry().getHooks(org.osgi.framework.hooks.service.FindHook.class);
        for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks)
        {
            org.osgi.framework.hooks.service.FindHook fh = m_reg.getService(getBundle(0), sr, false);
            if (fh != null)
            {
                try
                {
                    fh.find(this,
                            className,
                            expr,
                            !checkAssignable,
                            new ShrinkableCollection<ServiceReference<?>>(refList));
                }
                catch (Throwable th)
                {
                    System.err.println("Problem invoking service registry hook");
                    th.printStackTrace();
                }
                finally
                {
                    m_reg.ungetService(getBundle(0), sr, null);
                }
            }
        }

        if (refList.size() > 0)
        {
            return refList.toArray(new ServiceReference[refList.size()]);
        }

        return null;
    }

    public Filter createFilter(String filter) throws InvalidSyntaxException
    {
        return FrameworkUtil.createFilter(filter);
    }

    public void addServiceListener(ServiceListener listener)
    {
        try
        {
            addServiceListener(listener, null);
        }
        catch (InvalidSyntaxException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void addServiceListener(final ServiceListener listener, String filter)
            throws InvalidSyntaxException
    {
        m_dispatcher.addListener(this, ServiceListener.class, listener,
                filter == null ? null : FrameworkUtil.createFilter(filter));
    }

    public void addFrameworkListener(FrameworkListener listener)
    {
        m_dispatcher.addListener(this, FrameworkListener.class, listener,
                null);
    }

    public void addBundleListener(BundleListener listener)
    {
        m_dispatcher
                .addListener(this, BundleListener.class, listener, null);
    }

    @SuppressWarnings("unchecked")
    public <S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties)
    {
        return (ServiceRegistration<S>) registerService(clazz.getName(), service, properties);
    }

    @Override
    public <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Dictionary<String, ?> properties) {
        return (ServiceRegistration<S>) registerService(clazz.getName(), factory, properties);
    }

    @SuppressWarnings("unchecked")
    public <S> ServiceReference<S> getServiceReference(Class<S> clazz)
    {
        return (ServiceReference<S>) getServiceReference(clazz.getName());
    }

    @SuppressWarnings("unchecked")
    public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter)
            throws InvalidSyntaxException
    {
        ServiceReference<S>[] refs = (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter);
        if (refs == null)
        {
            return Collections.emptyList();
        }
        return Arrays.asList(refs);
    }

    public Bundle getBundle(String location)
    {
        for (Bundle bundle : m_bundles.values())
        {
            if (location.equals(bundle.getLocation()))
            {
                return bundle;
            }
        }
        return null;
    }
}
