/*
 * 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.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
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.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
import org.osgi.framework.VersionRange;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;
import org.osgi.service.startlevel.StartLevel;

import org.apache.felix.connect.felix.framework.ServiceRegistry;
import org.apache.felix.connect.felix.framework.util.EventDispatcher;
import org.apache.felix.connect.launch.BundleDescriptor;
import org.apache.felix.connect.launch.ClasspathScanner;
import org.apache.felix.connect.launch.PojoServiceRegistry;
import org.apache.felix.connect.launch.PojoServiceRegistryFactory;

public class PojoSR implements PojoServiceRegistry
{
    private final BundleContext m_context;
    private final ServiceRegistry m_registry = new ServiceRegistry(
            new ServiceRegistry.ServiceRegistryCallbacks()
            {
                public void serviceChanged(ServiceEvent event, Dictionary<String, ?> oldProps)
                {
                    m_dispatcher.fireServiceEvent(event, oldProps, m_bundles.get(0l));
                }
            });

    private final EventDispatcher m_dispatcher = new EventDispatcher(m_registry);
    private final Map<Long, Bundle> m_bundles = new HashMap<Long, Bundle>();
    private final Map<String, Object> bundleConfig;

    public static BundleDescriptor createSystemBundle() {
        final Map<String, String> headers = new HashMap<String, String>();
        headers.put(Constants.BUNDLE_SYMBOLICNAME, "org.apache.felix.connect");
        headers.put(Constants.BUNDLE_VERSION, "0.0.0");
        headers.put(Constants.BUNDLE_NAME, "System Bundle");
        headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
        headers.put(Constants.BUNDLE_VENDOR, "Apache Software Foundation");


        Revision revision = new Revision()
        {
            final long lastModified = System.currentTimeMillis();
            @Override
            public long getLastModified()
            {
                return lastModified;
            }

            @Override
            public Enumeration<String> getEntries()
            {
                return Collections.emptyEnumeration();
            }

            @Override
            public URL getEntry(String entryName)
            {
                return getClass().getClassLoader().getResource(entryName);
            }
        };
        Map<Class, Object> services = new HashMap<Class, Object>();
        services.put(FrameworkStartLevel.class, new FrameworkStartLevelImpl());
        return new BundleDescriptor(
                PojoSR.class.getClassLoader(),
                "felix-connect",
                headers,
                revision,
                services
                );
    }

    public PojoSR(Map<String, ?> config) throws Exception
    {
        this(config, null);
    }

    public PojoSR(Map<String, ?> config, BundleDescriptor systemBundle) throws Exception
    {
        if (systemBundle == null) {
            systemBundle = createSystemBundle();
        }
        bundleConfig = new HashMap<String, Object>(config);
        final Bundle b = new PojoSRBundle(
                        m_registry,
                        m_dispatcher,
                        m_bundles,
                        systemBundle.getUrl(),
                        0,
                        "org.apache.felix.connect",
                        new Version(0, 0, 1),
                                systemBundle.getRevision(),
                        systemBundle.getClassLoader(),
                        systemBundle.getHeaders(),
                        systemBundle.getServices(),
                        bundleConfig)
        {
            @Override
            public synchronized void start() throws BundleException
            {
                if (m_state != Bundle.RESOLVED)
                {
                    return;
                }
                m_dispatcher.startDispatching();
                m_state = Bundle.STARTING;

                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING, this));
                m_context = new PojoSRBundleContext(this, m_registry, m_dispatcher, m_bundles, bundleConfig);
                int i = 0;
                for (Bundle b : m_bundles.values())
                {
                    i++;
                    try
                    {
                        if (b != this)
                        {
                            b.start();
                        }
                    }
                    catch (Throwable t)
                    {
                        System.out.println("Unable to start bundle: " + i);
                        t.printStackTrace();
                    }
                }
                m_state = Bundle.ACTIVE;
                m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED, this));

                m_dispatcher.fireFrameworkEvent(new FrameworkEvent(FrameworkEvent.STARTED, this, null));
                super.start();
            }

            @Override
            public synchronized void stop() throws BundleException
            {
                if ((m_state == Bundle.STOPPING) || m_state == Bundle.RESOLVED)
                {
                    return;

                }
                else if (m_state != Bundle.ACTIVE)
                {
                    throw new BundleException("Can't stop pojosr because it is not ACTIVE");
                }
                final Bundle systemBundle = this;
                Runnable r = new Runnable()
                {

                    public void run()
                    {
                        m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPING, systemBundle));
                        for (Bundle b : m_bundles.values())
                        {
                            try
                            {
                                if (b != systemBundle)
                                {
                                    b.stop();
                                }
                            }
                            catch (Throwable t)
                            {
                                t.printStackTrace();
                            }
                        }
                        m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED, systemBundle));
                        m_state = Bundle.RESOLVED;
                        m_dispatcher.stopDispatching();
                    }
                };
                m_state = Bundle.STOPPING;
                if ("true".equalsIgnoreCase(System.getProperty("org.apache.felix.connect.events.sync")))
                {
                    r.run();
                }
                else
                {
                    new Thread(r).start();
                }
            }
        };
        m_bundles.put(0l, b);
        b.start();
        b.getBundleContext().registerService(StartLevel.class.getName(), new StartLevelImpl(), null);

        b.getBundleContext().registerService(PackageAdmin.class.getName(), new PackageAdminImpl(), null);
        m_context = b.getBundleContext();

        Collection<BundleDescriptor> scan = (Collection<BundleDescriptor>) config.get(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS);

        if (scan != null)
        {
            startBundles(scan);
        }
    }

    public void startBundles(Collection<BundleDescriptor> scan) throws Exception
    {
        for (BundleDescriptor desc : scan)
        {
            Revision revision = desc.getRevision();
            if (revision == null)
            {
                revision = buildRevision(desc);
            }
            Map<String, String> bundleHeaders = desc.getHeaders();
            Version osgiVersion;
            try
            {
                osgiVersion = Version.parseVersion(bundleHeaders.get(Constants.BUNDLE_VERSION));
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
                osgiVersion = Version.emptyVersion;
            }
            String sym = bundleHeaders.get(Constants.BUNDLE_SYMBOLICNAME);
            if (sym != null)
            {
                int idx = sym.indexOf(';');
                if (idx > 0)
                {
                    sym = sym.substring(0, idx);
                }
                sym = sym.trim();
            }

            Bundle bundle = new PojoSRBundle(
                    m_registry,
                    m_dispatcher,
                    m_bundles,
                    desc.getUrl(),
                    m_bundles.size(),
                    sym,
                    osgiVersion,
                    revision,
                    desc.getClassLoader(),
                    bundleHeaders,
                    desc.getServices(),
                    bundleConfig);
            m_bundles.put(bundle.getBundleId(), bundle);
        }


        for (Bundle bundle : m_bundles.values())
        {
            try
            {
                bundle.start();
            }
            catch (Throwable e)
            {
                System.out.println("Unable to start bundle: " + bundle);
                e.printStackTrace();
            }
        }

    }

    private Revision buildRevision(BundleDescriptor desc) throws IOException
    {
        Revision r;
        URL url = new URL(desc.getUrl());
        URL u = new URL(desc.getUrl() + "META-INF/MANIFEST.MF");
        if (u.toExternalForm().startsWith("file:"))
        {
            File root = new File(URLDecoder.decode(url.getFile(), "UTF-8"));
            r = new DirRevision(root);
        }
        else
        {
            URLConnection uc = u.openConnection();
            if (uc instanceof JarURLConnection)
            {
                String target = ((JarURLConnection) uc).getJarFileURL().toExternalForm();
                String prefix = null;
                if (!("jar:" + target + "!/").equals(desc.getUrl()))
                {
                    prefix = desc.getUrl().substring(("jar:" + target + "!/").length());
                }
                r = new JarRevision(
                        ((JarURLConnection) uc).getJarFile(),
                        ((JarURLConnection) uc).getJarFileURL(),
                        prefix,
                        uc.getLastModified());
            }
            else
            {
                r = new URLRevision(url, url.openConnection().getLastModified());
            }
        }
        return r;
    }

    public static void main(String[] args) throws Exception
    {
        Filter filter = null;
        Class<?> main = null;
        for (int i = 0; (args != null) && (i < args.length) && (i < 2); i++)
        {
            try
            {
                filter = FrameworkUtil.createFilter(args[i]);
            }
            catch (InvalidSyntaxException ie)
            {
                try
                {
                    main = PojoSR.class.getClassLoader().loadClass(args[i]);
                }
                catch (Exception ex)
                {
                    throw new IllegalArgumentException("Argument is neither a filter nor a class: " + args[i]);
                }
            }
        }
        Map<String, Object> config = new HashMap<String, Object>();
        config.put(
                PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS,
                (filter != null) ? new ClasspathScanner()
                        .scanForBundles(filter.toString()) : new ClasspathScanner()
                        .scanForBundles());
        new PojoServiceRegistryFactoryImpl().newPojoServiceRegistry(config);
        if (main != null)
        {
            int count = 0;
            if (filter != null)
            {
                count++;
            }
            count++;
            String[] newArgs = args;
            if (count > 0)
            {
                newArgs = new String[args.length - count];
                System.arraycopy(args, count, newArgs, 0, newArgs.length);
            }
            main.getMethod("main", String[].class).invoke(null, newArgs);
        }
    }

    public BundleContext getBundleContext()
    {
        return m_context;
    }

    @Override
    public void addServiceListener(ServiceListener listener, String filter) throws InvalidSyntaxException
    {
        m_context.addServiceListener(listener, filter);
    }

    @Override
    public void addServiceListener(ServiceListener listener)
    {
        m_context.addServiceListener(listener);
    }

    @Override
    public void removeServiceListener(ServiceListener listener)
    {
        m_context.removeServiceListener(listener);
    }

    @Override
    public ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties)
    {
        return m_context.registerService(clazzes, service, properties);
    }

    @Override
    public ServiceRegistration<?> registerService(String clazz, Object service, Dictionary<String, ?> properties)
    {
        return m_context.registerService(clazz, service, properties);
    }

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

    @Override
    public ServiceReference<?> getServiceReference(String clazz)
    {
        return m_context.getServiceReference(clazz);
    }

    @Override
    public <S> S getService(ServiceReference<S> reference)
    {
        return m_context.getService(reference);
    }

    @Override
    public boolean ungetService(ServiceReference<?> reference)
    {
        return m_context.ungetService(reference);
    }

    private static class FrameworkStartLevelImpl implements FrameworkStartLevel, BundleAware
    {

        private Bundle bundle;

        @Override
        public void setBundle(Bundle bundle)
        {
            this.bundle = bundle;
        }

        @Override
        public int getStartLevel()
        {
            return 0;
        }

        @Override
        public void setStartLevel(int startlevel, FrameworkListener... listeners)
        {
        }

        @Override
        public int getInitialBundleStartLevel()
        {
            return 0;
        }

        @Override
        public void setInitialBundleStartLevel(int startlevel)
        {
        }

        @Override
        public Bundle getBundle()
        {
            return bundle;
        }
    }

    private static class StartLevelImpl implements StartLevel
    {
        @Override
        public void setStartLevel(int startlevel)
        {
            // TODO Auto-generated method stub
        }

        @Override
        public void setInitialBundleStartLevel(int startlevel)
        {
            // TODO Auto-generated method stub
        }

        @Override
        public void setBundleStartLevel(Bundle bundle, int startlevel)
        {
            // TODO Auto-generated method stub
        }

        @Override
        public boolean isBundlePersistentlyStarted(Bundle bundle)
        {
            // TODO Auto-generated method stub
            return true;
        }

        @Override
        public boolean isBundleActivationPolicyUsed(Bundle bundle)
        {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public int getStartLevel()
        {
            // TODO Auto-generated method stub
            return 1;
        }

        @Override
        public int getInitialBundleStartLevel()
        {
            // TODO Auto-generated method stub
            return 1;
        }

        @Override
        public int getBundleStartLevel(Bundle bundle)
        {
            // TODO Auto-generated method stub
            return 1;
        }
    }

    private class PackageAdminImpl implements PackageAdmin
    {

        @Override
        public boolean resolveBundles(Bundle[] bundles)
        {
            return true;
        }

        @Override
        public void refreshPackages(Bundle[] bundles)
        {
            FrameworkEvent event = new FrameworkEvent(FrameworkEvent.PACKAGES_REFRESHED, m_bundles.get(0l), null);
            m_dispatcher.fireFrameworkEvent(event);
        }

        @Override
        public RequiredBundle[] getRequiredBundles(String symbolicName)
        {
            List list = new ArrayList();
            for (Bundle bundle : PojoSR.this.m_bundles.values())
            {
                if ((symbolicName == null) || (symbolicName.equals(bundle.getSymbolicName())))
                {
                    list.add(new RequiredBundleImpl(bundle));
                }
            }
            return (list.isEmpty())
                    ? null
                    : (RequiredBundle[]) list.toArray(new RequiredBundle[list.size()]);
        }

        @Override
        public Bundle[] getHosts(Bundle bundle)
        {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Bundle[] getFragments(Bundle bundle)
        {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public ExportedPackage[] getExportedPackages(String name)
        {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public ExportedPackage[] getExportedPackages(Bundle bundle)
        {
            List<ExportedPackage> list = new ArrayList<ExportedPackage>();
            // If a bundle is specified, then return its
            // exported packages.
            if (bundle != null)
            {
                getExportedPackages(bundle, list);
            }
            // Otherwise return all exported packages.
            else
            {
                for (Bundle b : m_bundles.values())
                {
                    getExportedPackages(b, list);
                }
            }
            return list.isEmpty() ? null : list.toArray(new ExportedPackage[list.size()]);
        }

        private void getExportedPackages(Bundle bundle, List<ExportedPackage> list)
        {
            // Since a bundle may have many revisions associated with it,
            // one for each revision in the cache, search each revision
            // to get all exports.
            for (BundleCapability cap : bundle.adapt(BundleWiring.class).getCapabilities(null))
            {
                if (cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE))
                {
                    list.add(new ExportedPackageImpl(cap));
                }
            }
        }

        @Override
        public ExportedPackage getExportedPackage(String name)
        {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Bundle[] getBundles(String symbolicName, String versionRange)
        {
            Set<Bundle> result = new HashSet<Bundle>();
            VersionRange range = versionRange != null ? new VersionRange(versionRange) : null;
            for (Bundle bundle : m_bundles.values())
            {
                if (symbolicName != null && !bundle.getSymbolicName().equals(symbolicName))
                {
                    continue;
                }
                if (range != null && !range.includes(bundle.getVersion()))
                {
                    continue;
                }
                result.add(bundle);
            }
            return result.isEmpty() ? null : result.toArray(new Bundle[result.size()]);
        }

        @Override
        public int getBundleType(Bundle bundle)
        {
            return bundle.adapt(BundleRevision.class).getTypes();
        }

        @Override
        public Bundle getBundle(Class clazz)
        {
            return m_context.getBundle();
        }
    }
}
