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

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.felix.bundlerepository.RepositoryAdmin;
import org.apache.felix.bundlerepository.Resource;
import org.apache.felix.utils.resource.CapabilityImpl;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;
import org.osgi.service.repository.ContentNamespace;
import org.osgi.service.repository.Repository;

class OSGiRepositoryImpl implements Repository
{
    private final RepositoryAdmin repository;

    OSGiRepositoryImpl(RepositoryAdmin repository)
    {
        this.repository = repository;
    }

    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements)
    {
        Map<Requirement, Collection<Capability>> m = new HashMap<Requirement, Collection<Capability>>();
        for (Requirement r : requirements)
        {
            m.put(r, findProviders(r));
        }
        return m;
    }

    private Collection<Capability> findProviders(Requirement req)
    {
        List<Capability> caps = new ArrayList<Capability>();
        if (IdentityNamespace.IDENTITY_NAMESPACE.equals(req.getNamespace()))
        {
            for(org.apache.felix.bundlerepository.Repository repo : repository.listRepositories())
            {
                for (org.apache.felix.bundlerepository.Resource res : repo.getResources())
                {
                    String f = req.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
                    try
                    {
                        addResourceForIdentity(res,
                            f == null ? null : FrameworkUtil.createFilter(f), caps);
                    }
                    catch (Exception e)
                    {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        else
        {
            org.apache.felix.bundlerepository.Resource[] resources = repository.discoverResources(
                new org.apache.felix.bundlerepository.Requirement[] {new OSGiRequirementAdapter(req)});
            OSGiRequirementAdapter adapter = new OSGiRequirementAdapter(req);
            for (org.apache.felix.bundlerepository.Resource resource : resources)
            {
                for (org.apache.felix.bundlerepository.Capability cap : resource.getCapabilities())
                {
                    if (adapter.isSatisfied(cap))
                        caps.add(new FelixCapabilityAdapter(cap, new FelixResourceAdapter(resource)));
                }
            }
        }

        return caps;
    }

    private void addResourceForIdentity(final org.apache.felix.bundlerepository.Resource res, Filter filter, List<Capability> caps)
        throws Exception
    {
        List<Capability> idCaps = new FelixResourceAdapter(res).getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
        if (idCaps.size() == 0)
            return;

        Capability idCap = idCaps.get(0); // there should only be one osgi.identity anyway
        if (filter != null)
        {
            if (!filter.matches(idCap.getAttributes()))
                return;
        }
        caps.add(idCap);
    }

    static CapabilityImpl newOSGiIdentityCapability(org.osgi.resource.Resource or, org.apache.felix.bundlerepository.Resource res)
    {
        @SuppressWarnings("unchecked")
        Map<String, Object> idAttrs = new HashMap<String, Object>(res.getProperties());

        // Set a number of specific properties that need to be translated
        idAttrs.put(IdentityNamespace.IDENTITY_NAMESPACE, res.getSymbolicName());

        if (idAttrs.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE) == null)
            idAttrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, IdentityNamespace.TYPE_BUNDLE);

        return new CapabilityImpl(or, IdentityNamespace.IDENTITY_NAMESPACE, Collections.<String, String> emptyMap(), idAttrs);
    }

    static CapabilityImpl newOSGiContentCapability(org.osgi.resource.Resource or, Resource resource)
    {
        final String uri = resource.getURI();
        LazyStringMap.LazyValue<String> content = new LazyStringMap.LazyValue<String>() {
            public String compute() {
                // This is expensive to do, so only compute it when actually obtained...
                try {
                    return OSGiRepositoryImpl.getSHA256(uri);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } catch (NoSuchAlgorithmException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        Object mime = resource.getProperties().get("mime");
        if (mime == null)
            mime = "application/vnd.osgi.bundle";

        Map<String, Object> contentAttrs = new LazyStringMap<Object>(4);
        contentAttrs.put(ContentNamespace.CAPABILITY_MIME_ATTRIBUTE, mime);
        contentAttrs.put(ContentNamespace.CAPABILITY_SIZE_ATTRIBUTE, resource.getSize());
        contentAttrs.put(ContentNamespace.CAPABILITY_URL_ATTRIBUTE, uri);
        contentAttrs.put(ContentNamespace.CONTENT_NAMESPACE, content);
        return new CapabilityImpl(or, ContentNamespace.CONTENT_NAMESPACE, Collections.<String, String> emptyMap(), contentAttrs);
    }

    static String getSHA256(String uri) throws IOException, NoSuchAlgorithmException // TODO find a good place for this
    {
        InputStream is = new URL(uri).openStream();
        MessageDigest md = MessageDigest.getInstance("SHA-256");

        // Use a digest inputstream as using byte arrays directly to compute the SHA-256 can
        // have big effects on memory consumption. I.e. you don't want to have to read the
        // entire resource in memory. We rather stream it through...
        DigestInputStream dis = new DigestInputStream(is, md);

        byte[] buffer = new byte[16384];
        while (dis.read(buffer) != -1) {
            // we just drain the stream here to compute the Message Digest
        }

        StringBuilder sb = new StringBuilder(64); // SHA-256 is always 64 hex characters
        for (byte b : md.digest())
        {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

}
