/*
 * 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.LinkedList;
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<?, ?> oldProps)
                {
                    m_dispatcher.fireServiceEvent(event, (Dictionary<String, ?>) 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;
    private final boolean m_hasVFS;

    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.enumeration(Collections.EMPTY_LIST);
            }

            @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(),
                "System Bundle",
                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();

        boolean hasVFS;
        try
        {
            hasVFS = org.jboss.vfs.VFS.class != null;
        } catch (Throwable t) {
            hasVFS = false;
        }
        m_hasVFS = hasVFS;

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

        if (scan != null)
        {
            Object autoStart = config.get(PojoServiceRegistryFactory.BUNDLES_AUTOSTART);
            if(autoStart == null || Boolean.TRUE.equals(autoStart))
            {
                startBundles(scan);
            }
            else
            {
                for (BundleDescriptor desc : scan) {
                    registerBundle(desc);
                }
            }
        }
    }

    public void startBundles(Collection<BundleDescriptor> scan) throws Exception {
        List<Bundle> bundles = new LinkedList<Bundle>();

        for (BundleDescriptor desc : scan)
        {
            Bundle bundle = registerBundle(desc);
            bundles.add(bundle);
        }

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

    public Bundle registerBundle(BundleDescriptor desc) throws Exception
    {
        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);

        return bundle;
    }

    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");
        String extF = u.toExternalForm();
        if (extF.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()) && desc.getUrl().startsWith("jar:" + target + "!/"))
                {
                    System.out.println(desc.getUrl() + " " + target);
                    prefix = desc.getUrl().substring(("jar:" + target + "!/").length());
                }
                r = new JarRevision(
                        ((JarURLConnection) uc).getJarFile(),
                        ((JarURLConnection) uc).getJarFileURL(),
                        prefix,
                        uc.getLastModified());
            }
            else if (m_hasVFS && extF.startsWith("vfs"))
            {
                r = new VFSRevision(url, url.openConnection().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();
        }
    }
}
