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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.felix.service.command.Descriptor;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;

public class Inspect
{
    public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";

    public static final String CAPABILITY = "capability";
    public static final String REQUIREMENT = "requirement";

    private static final String EMPTY_MESSAGE = "[EMPTY]";
    private static final String UNUSED_MESSAGE = "[UNUSED]";
    private static final String UNRESOLVED_MESSAGE = "[UNRESOLVED]";

    private final BundleContext m_bc;

    public Inspect(BundleContext bc)
    {
        m_bc = bc;
    }

    @Descriptor("inspects bundle capabilities and requirements")
    public String inspect(
        @Descriptor("('capability' | 'requirement')") String direction,
        @Descriptor("(<namespace> | 'service')") String namespace,
        @Descriptor("target bundles") Bundle[] bundles)
    {
        return inspect(m_bc, direction, namespace, bundles);
    }

    private static String inspect(
        BundleContext bc, String direction, String namespace, Bundle[] bundles)
    {
        // Verify arguments.
        if (isValidDirection(direction))
        {
            bundles = ((bundles == null) || (bundles.length == 0))
                ? bc.getBundles() : bundles;

            if (CAPABILITY.startsWith(direction))
            {
                return printCapabilities(bc, Util.parseSubstring(namespace), bundles);
            }
            else
            {
                return printRequirements(bc, Util.parseSubstring(namespace), bundles);
            }
        }

        return "Invalid argument: " + direction;
    }

    public static String printCapabilities(
        BundleContext bc, List<String> namespace, Bundle[] bundles)
    {
        try (Formatter f = new Formatter()) {
            for (Bundle b : bundles)
            {
                // Print out any matching generic capabilities.
                BundleWiring wiring = b.adapt(BundleWiring.class);
                if (wiring != null)
                {
                    String title = b + " provides:";
                    f.format("%s%n%s%n", title, Util.getUnderlineString(title.length()));

                    // Print generic capabilities for matching namespaces.
                    boolean matches = printMatchingCapabilities(wiring, namespace, f);

                    // Handle service capabilities separately, since they aren't part
                    // of the generic model in OSGi.
                    if (matchNamespace(namespace, NONSTANDARD_SERVICE_NAMESPACE))
                    {
                        matches |= printServiceCapabilities(b, f);
                    }

                    // If there were no capabilities for the specified namespace,
                    // then say so.
                    if (!matches)
                    {
                        f.format("%s %s%n", Util.unparseSubstring(namespace), EMPTY_MESSAGE);
                    }
                }
                else
                {
                    f.format("Bundle %s is not resolved.",
                        b.getBundleId());
                }
            }
            return f.toString();
        }
    }

    private static boolean printMatchingCapabilities(BundleWiring wiring, List<String> namespace, Formatter f)
    {
        List<BundleWire> wires = wiring.getProvidedWires(null);
        Map<BundleCapability, List<BundleWire>> aggregateCaps =
            aggregateCapabilities(namespace, wires);
        List<BundleCapability> allCaps = wiring.getCapabilities(null);
        boolean matches = false;
        for (BundleCapability cap : allCaps)
        {
            if (matchNamespace(namespace, cap.getNamespace()))
            {
                if ("osgi.service".equals(cap.getNamespace())) {
                    continue;
                }
                matches = true;
                List<BundleWire> dependents = aggregateCaps.get(cap);
                Object keyAttr =
                    cap.getAttributes().get(cap.getNamespace());
                if ("osgi.native".equals(cap.getNamespace()))
                {
                    f.format("%s with properties:%n", cap.getNamespace());
                    List<Entry<String, Object>> sortedEntries = 
                            new ArrayList<Entry<String, Object>>(cap.getAttributes().entrySet());
                    Collections.sort(sortedEntries, new Comparator<Entry<String, Object>>() {
                        @Override
                        public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {
                            return o1.getKey().compareTo(o2.getKey());
                        }});
                    
                    for (Entry<String, Object> e : sortedEntries) {
                        f.format("   %s = %s%n", e.getKey(), e.getValue());
                    }
                    
                    if (dependents != null)
                    {
                        f.format("   required by:%n");
                        for (BundleWire wire : dependents) {
                            f.format("      %s%n", wire.getRequirerWiring().getBundle());
                        }
                    }
                    else
                    {
                        f.format("   %s%n", UNUSED_MESSAGE);
                    }
                }
                else if (dependents != null)
                {
                    if (keyAttr != null)
                    {
                        f.format("%s; %s %s required by:%n",
                            cap.getNamespace(),
                            format(keyAttr),
                            getVersionFromCapability(cap));
                    }
                    else
                    {
                        f.format("%s required by:%n", cap.toString());
                    }
                    for (BundleWire wire : dependents)
                    {
                        f.format("   %s%n", wire.getRequirerWiring().getBundle());
                    }
                }
                else if (keyAttr != null)
                {
                    f.format("%s; %s %s %s%n",
                        cap.getNamespace(),
                        format(keyAttr),
                        getVersionFromCapability(cap),
                        UNUSED_MESSAGE);
                }
                else
                {
                    f.format("%s %s%n", cap, UNUSED_MESSAGE);
                }
            }
        }
        return matches;
    }

    private static String format(Object object) {
        String retVal;
        if (object.getClass().isArray() || object instanceof Collection) {        	
            StringBuffer buffer = new StringBuffer();
            @SuppressWarnings("rawtypes")
            Iterable formatTarget = object.getClass().isArray() ? Arrays.asList(object) : (Iterable) object;
            for (Object elem : formatTarget) {
                if (buffer.length()>0) {
                    buffer.append(',');
                }
                buffer.append(elem.toString());
            }
            retVal = buffer.toString();
        }
        else {
            retVal = String.valueOf(object);
        }
        return retVal;
    }
    
    private static Map<BundleCapability, List<BundleWire>> aggregateCapabilities(
        List<String> namespace, List<BundleWire> wires)
    {
        // Aggregate matching capabilities.
        Map<BundleCapability, List<BundleWire>> map =
                new HashMap<>();
        for (BundleWire wire : wires)
        {
            if (matchNamespace(namespace, wire.getCapability().getNamespace()))
            {
                List<BundleWire> dependents = map.get(wire.getCapability());
                if (dependents == null)
                {
                    dependents = new ArrayList<>();
                    map.put(wire.getCapability(), dependents);
                }
                dependents.add(wire);
            }
        }
        return map;
    }

    static boolean printServiceCapabilities(Bundle b, Formatter f)
    {
        boolean matches = false;

        try
        {
            ServiceReference<?>[] refs = b.getRegisteredServices();

            if ((refs != null) && (refs.length > 0))
            {
                matches = true;
                // Print properties for each service.
                for (ServiceReference<?> ref : refs)
                {
                    // Print object class with "namespace".
                    f.format("%s; %s with properties:%n",
                        NONSTANDARD_SERVICE_NAMESPACE,
                        Util.getValueString(ref.getProperty("objectClass")));
                    // Print service properties.
                    String[] keys = ref.getPropertyKeys();
                    for (String key : keys)
                    {
                        if (!key.equalsIgnoreCase(Constants.OBJECTCLASS))
                        {
                            Object v = ref.getProperty(key);
                            f.format("   %s = %s%n", key, Util.getValueString(v));
                        }
                    }
                    Bundle[] users = ref.getUsingBundles();
                    if ((users != null) && (users.length > 0))
                    {
                        f.format("   Used by:%n");
                        for (Bundle user : users)
                        {
                            f.format("      %s%n", user);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            f.format("%s%n", ex.toString());
        }

        return matches;
    }

    public static String printRequirements(
        BundleContext bc, List<String> namespace, Bundle[] bundles)
    {
        try (Formatter f = new Formatter()) {
            for (Bundle b : bundles)
            {
                // Print out any matching generic requirements.
                BundleWiring wiring = b.adapt(BundleWiring.class);
                if (wiring != null)
                {
                    String title = b + " requires:";
                    f.format("%s%n%s%n", title, Util.getUnderlineString(title.length()));
                    boolean matches = printMatchingRequirements(wiring, namespace, f);

                    // Handle service requirements separately, since they aren't part
                    // of the generic model in OSGi.
                    if (matchNamespace(namespace, NONSTANDARD_SERVICE_NAMESPACE))
                    {
                        matches |= printServiceRequirements(b, f);
                    }

                    // If there were no requirements for the specified namespace,
                    // then say so.
                    if (!matches)
                    {
                        f.format("%s %s%n", Util.unparseSubstring(namespace), EMPTY_MESSAGE);
                    }
                }
                else
                {
                    f.format("Bundle %s is not resolved.%n",
                        b.getBundleId());
                }
            }
            return f.toString();
        }
    }

    private static boolean printMatchingRequirements(BundleWiring wiring, List<String> namespace, Formatter f)
    {
        List<BundleWire> wires = wiring.getRequiredWires(null);
        Map<BundleRequirement, List<BundleWire>> aggregateReqs =
            aggregateRequirements(namespace, wires);
        List<BundleRequirement> allReqs = wiring.getRequirements(null);
        boolean matches = false;
        for (BundleRequirement req : allReqs)
        {
            if (matchNamespace(namespace, req.getNamespace()))
            {
                matches = true;
                List<BundleWire> providers = aggregateReqs.get(req);
                if (providers != null)
                {
                    f.format("%s; %s resolved by:%n",
                        req.getNamespace(),
                        req.getDirectives().get(Constants.FILTER_DIRECTIVE));
                    for (BundleWire wire : providers)
                    {
                        String msg;
                        Object keyAttr =
                            wire.getCapability().getAttributes()
                                .get(wire.getCapability().getNamespace());
                        if (keyAttr != null)
                        {
                            msg = wire.getCapability().getNamespace()
                                + "; "
                                + keyAttr
                                + " "
                                + getVersionFromCapability(wire.getCapability());
                        }
                        else
                        {
                            msg = wire.getCapability().toString();
                        }
                        f.format("   %s from %s%n", msg, wire.getProviderWiring().getBundle());
                    }
                }
                else
                {
                    f.format("%s; %s %s%n",
                        req.getNamespace(),
                        req.getDirectives().get(Constants.FILTER_DIRECTIVE),
                        UNRESOLVED_MESSAGE);
                }
            }
        }
        return matches;
    }

    private static Map<BundleRequirement, List<BundleWire>> aggregateRequirements(
        List<String> namespace, List<BundleWire> wires)
    {
        // Aggregate matching capabilities.
        Map<BundleRequirement, List<BundleWire>> map =
                new HashMap<>();
        for (BundleWire wire : wires)
        {
            if (matchNamespace(namespace, wire.getRequirement().getNamespace()))
            {
                List<BundleWire> providers = map.get(wire.getRequirement());
                if (providers == null)
                {
                    providers = new ArrayList<>();
                    map.put(wire.getRequirement(), providers);
                }
                providers.add(wire);
            }
        }
        return map;
    }

    static boolean printServiceRequirements(Bundle b, Formatter f)
    {
        boolean matches = false;

        try
        {
            ServiceReference<?>[] refs = b.getServicesInUse();

            if ((refs != null) && (refs.length > 0))
            {
                matches = true;
                // Print properties for each service.
                for (ServiceReference<?> ref : refs)
                {
                    // Print object class with "namespace".
                    f.format("%s; %s provided by:%n   %s%n",
                        NONSTANDARD_SERVICE_NAMESPACE,
                        Util.getValueString(ref.getProperty("objectClass")),
                        ref.getBundle());
                }
            }
        }
        catch (Exception ex)
        {
            System.err.println(ex.toString());
        }

        return matches;
    }

    private static String getVersionFromCapability(BundleCapability c)
    {
        Object o = c.getAttributes().get(Constants.VERSION_ATTRIBUTE);
        if (o == null)
        {
            o = c.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
        }
        return (o == null) ? "" : o.toString();
    }

    private static boolean matchNamespace(List<String> namespace, String actual)
    {
        return Util.compareSubstring(namespace, actual);
    }

    private static boolean isValidDirection(String direction)
    {
        return (CAPABILITY.startsWith(direction) || REQUIREMENT.startsWith(direction));
    }
}