/*
 * 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.io.InputStream;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.felix.connect.felix.framework.DTOFactory;
import org.apache.felix.connect.felix.framework.ServiceRegistry;
import org.apache.felix.connect.felix.framework.util.EventDispatcher;
import org.apache.felix.connect.felix.framework.util.MapToDictionary;
import org.apache.felix.connect.felix.framework.util.StringMap;
import org.osgi.dto.DTO;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleRevisions;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Wire;

class PojoSRBundle implements Bundle, BundleRevisions
{
    private final Revision m_revision;
    private final Map<String, String> m_headers;
    private final Version m_version;
    private final String m_location;
    private final Map<Long, Bundle> m_bundles;
    private final ServiceRegistry m_registry;
    private final String m_activatorClass;
    private final long m_id;
    private final String m_symbolicName;
    private volatile BundleActivator m_activator = null;
    volatile int m_state = Bundle.RESOLVED;
    volatile BundleContext m_context = null;
    private final EventDispatcher m_dispatcher;
    private final ClassLoader m_classLoader;
    private final Map<Class, Object> m_services;
    private final Map m_config;

    public PojoSRBundle(ServiceRegistry registry,
                        EventDispatcher dispatcher,
                        Map<Long, Bundle> bundles,
                        String location,
                        long id,
                        String symbolicName,
                        Version version,
                        Revision revision,
                        ClassLoader classLoader,
                        Map<String, String> headers,
                        Map<Class, Object> services,
                        Map<? extends Object, ? extends Object> config)
    {
        m_revision = revision;
        m_headers = headers;
        m_version = version;
        m_location = location;
        m_registry = registry;
        m_dispatcher = dispatcher;
        m_activatorClass = headers.get(Constants.BUNDLE_ACTIVATOR);
        m_id = id;
        m_symbolicName = symbolicName;
        m_bundles = bundles;
        m_classLoader = classLoader;
        m_services = services;
        m_config = config;
        if (classLoader instanceof BundleAware) {
            ((BundleAware) classLoader).setBundle(this);
        }
        if (services != null) {
            for (Object o : services.values()) {
                if (o instanceof BundleAware) {
                    ((BundleAware) o).setBundle(this);
                }
            }
        }
    }

    @Override
    public int getState()
    {
        return m_state;
    }

    @Override
    public void start(int options) throws BundleException
    {
        // TODO: lifecycle - fix this
        start();
    }

    @Override
    public synchronized void start() throws BundleException
    {
        if (m_state != Bundle.RESOLVED)
        {
            if (m_state == Bundle.ACTIVE)
            {
                return;
            }
            throw new BundleException("Bundle is in wrong state for start");
        }
        try
        {
            m_state = Bundle.STARTING;

            m_context = new PojoSRBundleContext(this, m_registry, m_dispatcher, m_bundles, m_config);
            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTING, this));
            if (m_activatorClass != null)
            {
                m_activator = (BundleActivator) m_classLoader.loadClass(m_activatorClass).newInstance();
                m_activator.start(m_context);
            }
            m_state = Bundle.ACTIVE;
            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STARTED, this));
        }
        catch (Throwable ex)
        {
            m_state = Bundle.RESOLVED;
            m_activator = null;
            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED, this));
            throw new BundleException("Unable to start bundle", ex);
        }
    }

    @Override
    public void stop(int options) throws BundleException
    {
        // TODO: lifecycle - fix this
        stop();
    }

    @Override
    public synchronized void stop() throws BundleException
    {
        if (m_state != Bundle.ACTIVE)
        {
            if (m_state == Bundle.RESOLVED)
            {
                return;
            }
            throw new BundleException("Bundle is in wrong state for stop");
        }
        try
        {
            m_state = Bundle.STOPPING;
            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPING,
                    this));
            if (m_activator != null)
            {
                m_activator.stop(m_context);
            }
        }
        catch (Throwable ex)
        {
            throw new BundleException("Error while stopping bundle", ex);
        }
        finally
        {
            m_registry.unregisterServices(this);
            m_dispatcher.removeListeners(m_context);
            m_activator = null;
            m_context = null;
            m_state = Bundle.RESOLVED;
            m_dispatcher.fireBundleEvent(new BundleEvent(BundleEvent.STOPPED,
                    this));
        }
    }

    @Override
    public void update(InputStream input) throws BundleException
    {
        throw new BundleException("pojosr bundles can't be updated");
    }

    @Override
    public void update() throws BundleException
    {
        throw new BundleException("pojosr bundles can't be updated");
    }

    @Override
    public void uninstall() throws BundleException
    {
        throw new BundleException("pojosr bundles can't be uninstalled");
    }

    @Override
    public Dictionary<String, String> getHeaders()
    {
        return getHeaders(Locale.getDefault().toString());
    }

    @Override
    public long getBundleId()
    {
        return m_id;
    }

    @Override
    public String getLocation()
    {
        return m_location;
    }

    @Override
    public ServiceReference<?>[] getRegisteredServices()
    {
        return m_registry.getRegisteredServices(this);
    }

    @Override
    public ServiceReference<?>[] getServicesInUse()
    {
        return m_registry.getServicesInUse(this);
    }

    @Override
    public boolean hasPermission(Object permission)
    {
        // TODO: security - fix this
        return true;
    }

    @Override
    public URL getResource(String name)
    {
        URL result = getEntry(name);
        return result != null ? result : m_classLoader.getResource(name != null ? name.trim().startsWith("/") ? name.substring(1) : name : null);
    }

    @Override
    public Dictionary<String, String> getHeaders(String locale)
    {
        return new MapToDictionary<String, String>(getCurrentLocalizedHeader(locale));
    }

    Map<String, String> getCurrentLocalizedHeader(String locale)
    {
        Map<String, String> result = null;

        // Spec says empty local returns raw headers.
        if ((locale == null) || (locale.length() == 0))
        {
            result = (Map) new StringMap(m_headers);
        }

        // If we have no result, try to get it from the cached headers.
        if (result == null)
        {
            synchronized (m_cachedHeaders)
            {
                // If the bundle is uninstalled, then the cached headers should
                // only contain the localized headers for the default locale at
                // the time of uninstall, so just return that.
                if (getState() == Bundle.UNINSTALLED)
                {
                    result = m_cachedHeaders.values().iterator().next();
                }
                // If the bundle has been updated, clear the cached headers.
                else if (getLastModified() > m_cachedHeadersTimestamp)
                {
                    m_cachedHeaders.clear();
                }
                // Otherwise, returned the cached headers if they exist.
                else
                {
                    // Check if headers for this locale have already been resolved
                    result = m_cachedHeaders.get(locale);
                }
            }
        }

        // If the requested locale is not cached, then try to create it.
        if (result == null)
        {
            // Get a modifiable copy of the raw headers.
            Map<String, String> headers = (Map) new StringMap(m_headers);
            // Assume for now that this will be the result.
            result = headers;

            // Check to see if we actually need to localize anything
            boolean localize = false;
            for (String s : headers.values())
            {
                if ((s).startsWith("%"))
                {
                    localize = true;
                    break;
                }
            }

            if (!localize)
            {
                // If localization is not needed, just cache the headers and
                // return
                // them as-is. Not sure if this is useful
                updateHeaderCache(locale, headers);
            }
            else
            {
                // Do localization here and return the localized headers
                String basename = headers.get(Constants.BUNDLE_LOCALIZATION);
                if (basename == null)
                {
                    basename = Constants.BUNDLE_LOCALIZATION_DEFAULT_BASENAME;
                }

                // Create ordered list of files to load properties from
                List<String> resourceList = createLocalizationResourceList(basename, locale);

                // Create a merged props file with all available props for this
                // locale
                boolean found = false;
                Properties mergedProperties = new Properties();
                for (String aResourceList : resourceList)
                {
                    URL temp = m_revision.getEntry(aResourceList + ".properties");
                    if (temp != null)
                    {
                        found = true;
                        try
                        {
                            mergedProperties.load(temp.openConnection().getInputStream());
                        }
                        catch (IOException ex)
                        {
                            // File doesn't exist, just continue loop
                        }
                    }
                }

                // If the specified locale was not found, then the spec says we
                // should
                // return the default localization.
                if (!found && !locale.equals(Locale.getDefault().toString()))
                {
                    result = getCurrentLocalizedHeader(Locale.getDefault().toString());
                }
                // Otherwise, perform the localization based on the discovered
                // properties and cache the result.
                else
                {
                    // Resolve all localized header entries
                    for (Map.Entry<String, String> entry : headers.entrySet())
                    {
                        String value = entry.getValue();
                        if (value.startsWith("%"))
                        {
                            String newvalue;
                            String key = value.substring(value.indexOf("%") + 1);
                            newvalue = mergedProperties.getProperty(key);
                            if (newvalue == null)
                            {
                                newvalue = key;
                            }
                            entry.setValue(newvalue);
                        }
                    }

                    updateHeaderCache(locale, headers);
                }
            }
        }

        return result;
    }

    private void updateHeaderCache(String locale, Map<String, String> localizedHeaders)
    {
        synchronized (m_cachedHeaders)
        {
            m_cachedHeaders.put(locale, localizedHeaders);
            m_cachedHeadersTimestamp = System.currentTimeMillis();
        }
    }

    private final Map<String, Map<String, String>> m_cachedHeaders = new HashMap<String, Map<String, String>>();
    private long m_cachedHeadersTimestamp;

    private static List<String> createLocalizationResourceList(String basename, String locale)
    {
        List<String> result = new ArrayList<String>(4);

        StringTokenizer tokens;
        StringBuilder tempLocale = new StringBuilder(basename);

        result.add(tempLocale.toString());

        if (locale.length() > 0)
        {
            tokens = new StringTokenizer(locale, "_");
            while (tokens.hasMoreTokens())
            {
                tempLocale.append("_").append(tokens.nextToken());
                result.add(tempLocale.toString());
            }
        }
        return result;
    }

    public String getSymbolicName()
    {
        return m_symbolicName;
    }

    public Class<?> loadClass(String name) throws ClassNotFoundException
    {
        return m_classLoader.loadClass(name);
    }

    @Override
    public Enumeration<URL> getResources(String name) throws IOException
    {
        // TODO: module - implement this based on the revision
        return m_classLoader.getResources(name);
    }

    @Override
    public Enumeration<String> getEntryPaths(String path)
    {
        Enumeration<String> result = new EntryFilterEnumeration<String>(m_revision, false, path, null, false,
                false);
        return result.hasMoreElements() ? result : null;
    }

    @Override
    public URL getEntry(String path)
    {
        URL result = m_revision.getEntry(path);
        return result;
    }

    @Override
    public long getLastModified()
    {
        return m_revision.getLastModified();
    }

    @Override
    public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse)
    {
        // TODO: module - implement this based on the revision
        Enumeration<URL> result = new EntryFilterEnumeration<URL>(m_revision, true, path, filePattern, recurse, true);
        return result.hasMoreElements() ? result : null;
    }

    @Override
    public BundleContext getBundleContext()
    {
        return m_context;
    }

    @Override
    public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType)
    {
        // TODO: security - fix this
        return new HashMap<X509Certificate, List<X509Certificate>>();
    }

    @Override
    public Version getVersion()
    {
        return m_version;
    }

    @Override
    public boolean equals(Object o)
    {
        if (o instanceof PojoSRBundle)
        {
            return ((PojoSRBundle) o).m_id == m_id;
        }
        return false;
    }

    @Override
    public int compareTo(Bundle o)
    {
        long thisBundleId = this.getBundleId();
        long thatBundleId = o.getBundleId();
        return (thisBundleId < thatBundleId ? -1 : (thisBundleId == thatBundleId ? 0 : 1));
    }

    @SuppressWarnings("unchecked")
    public <A> A adapt(Class<A> type)
    {
        if (m_services != null && m_services.containsKey(type))
        {
            return (A) m_services.get(type);
        }
        if (type.isInstance(this))
        {
            return (A) this;
        }
        if (type == BundleWiring.class)
        {
            return (A) new BundleWiringImpl(this, m_classLoader);
        }
        if (type == BundleRevision.class)
        {
            return (A) new BundleRevisionImpl(this);
        }
        if (type == BundleStartLevel.class)
        {
            return (A) new BundleStartLevelImpl(this);
        }
        if (DTO.class.isAssignableFrom(type) ||
            DTO[].class.isAssignableFrom(type))
        {
            return DTOFactory.createDTO(this, type);
        }
        return null;
    }
    
    public File getDataFile(String filename)
    {
        return m_context.getDataFile(filename);
    }

    public String toString()
    {
        String sym = getSymbolicName();
        if (sym != null)
        {
            return sym + " [" + getBundleId() + "]";
        }
        return "[" + getBundleId() + "]";
    }

    @Override
    public List<BundleRevision> getRevisions()
    {
        return Arrays.asList(adapt(BundleRevision.class));
    }

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


    public static class BundleStartLevelImpl implements BundleStartLevel
    {
        private final Bundle bundle;

        public BundleStartLevelImpl(Bundle bundle)
        {
            this.bundle = bundle;
        }

        public int getStartLevel()
        {
            // TODO Implement this?
            return 1;
        }

        public void setStartLevel(int startlevel)
        {
            // TODO Implement this?
        }

        public boolean isPersistentlyStarted()
        {
            return true;
        }

        public boolean isActivationPolicyUsed()
        {
            return false;
        }

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

    public static class BundleRevisionImpl implements BundleRevision
    {
        private final Bundle bundle;

        public BundleRevisionImpl(Bundle bundle)
        {
            this.bundle = bundle;
        }

        @Override
        public String getSymbolicName()
        {
            return bundle.getSymbolicName();
        }

        @Override
        public Version getVersion()
        {
            return bundle.getVersion();
        }

        @Override
        public List<BundleCapability> getDeclaredCapabilities(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<BundleRequirement> getDeclaredRequirements(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public int getTypes()
        {
            if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
            {
                return BundleRevision.TYPE_FRAGMENT;
            }
            return 0;
        }

        @Override
        public BundleWiring getWiring()
        {
            return bundle.adapt(BundleWiring.class);
        }

        @Override
        public List<Capability> getCapabilities(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<Requirement> getRequirements(String namespace)
        {
            return Collections.emptyList();
        }

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

    public static class BundleWiringImpl implements BundleWiring
    {

        private final Bundle bundle;
        private final ClassLoader classLoader;

        public BundleWiringImpl(Bundle bundle, ClassLoader classLoader)
        {
            this.bundle = bundle;
            this.classLoader = classLoader;
        }

        @Override
        public boolean isInUse()
        {
            return true;
        }

        @Override
        public boolean isCurrent()
        {
            return true;
        }

        @Override
        public BundleRevision getRevision()
        {
            return bundle.adapt(BundleRevision.class);
        }

        @Override
        public List<BundleRequirement> getRequirements(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<BundleWire> getRequiredWires(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<BundleWire> getProvidedWires(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public ClassLoader getClassLoader()
        {
            return classLoader;
        }

        @Override
        public List<BundleCapability> getCapabilities(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<Capability> getResourceCapabilities(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<Requirement> getResourceRequirements(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<Wire> getProvidedResourceWires(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public List<Wire> getRequiredResourceWires(String namespace)
        {
            return Collections.emptyList();
        }

        @Override
        public BundleRevision getResource()
        {
            return getRevision();
        }

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

        @Override
        public List<URL> findEntries(String path, String filePattern, int options)
        {
            List<URL> result = new ArrayList<URL>();
            for (Enumeration<URL> e = bundle.findEntries(path, filePattern, options == BundleWiring.FINDENTRIES_RECURSE); e.hasMoreElements(); )
            {
                result.add(e.nextElement());
            }
            return result;
        }

        @Override
        public Collection<String> listResources(String path, String filePattern, int options)
        {
            // TODO: this is wrong, we should return the resource names
            Collection<String> result = new ArrayList<String>();
            for (URL u : findEntries(path, filePattern, options))
            {
                result.add(u.toString());
            }
            return result;
        }

    }

}
