/*
 * 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.HashMap;
import java.util.List;

import java.util.Map;
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;
import org.osgi.service.packageadmin.ExportedPackage;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.packageadmin.RequiredBundle;

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 void inspect(
        @Descriptor("('capability' | 'requirement')") String direction,
        @Descriptor("(<namespace> | 'service')") String namespace,
        @Descriptor("target bundles") Bundle[] bundles)
    {
        inspect(m_bc, direction, namespace, bundles);
    }

    private static void 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))
            {
                printCapabilities(bc, Util.parseSubstring(namespace), bundles);
            }
            else
            {
                printRequirements(bc, Util.parseSubstring(namespace), bundles);
            }
        }
        else
        {
            if (!isValidDirection(direction))
            {
                System.out.println("Invalid argument: " + direction);
            }
        }
    }

    public static void printCapabilities(
        BundleContext bc, List<String> namespace, Bundle[] bundles)
    {
        boolean separatorNeeded = false;
        for (Bundle b : bundles)
        {
            if (separatorNeeded)
            {
                System.out.println("");
            }

            // Print out any matching generic capabilities.
            BundleWiring wiring = b.adapt(BundleWiring.class);
            if (wiring != null)
            {
                String title = b + " provides:";
                System.out.println(title);
                System.out.println(Util.getUnderlineString(title.length()));

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

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

                // If there were no capabilities for the specified namespace,
                // then say so.
                if (!matches)
                {
                    System.out.println(Util.unparseSubstring(namespace) + " " + EMPTY_MESSAGE);
                }
            }
            else
            {
                System.out.println("Bundle "
                    + b.getBundleId()
                    + " is not resolved.");
            }
            separatorNeeded = true;
        }
    }

    private static boolean printMatchingCapabilities(BundleWiring wiring, List<String> namespace)
    {
        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()))
            {
                matches = true;
                List<BundleWire> dependents = aggregateCaps.get(cap);
                Object keyAttr =
                    cap.getAttributes().get(cap.getNamespace());
                if (dependents != null)
                {
                    String msg;
                    if (keyAttr != null)
                    {
                        msg = cap.getNamespace()
                            + "; "
                            + keyAttr
                            + " "
                            + getVersionFromCapability(cap);
                    }
                    else
                    {
                        msg = cap.toString();
                    }
                    msg = msg + " required by:";
                    System.out.println(msg);
                    for (BundleWire wire : dependents)
                    {
                        System.out.println("   " + wire.getRequirerWiring().getBundle());
                    }
                }
                else if (keyAttr != null)
                {
                    System.out.println(cap.getNamespace()
                        + "; "
                        + cap.getAttributes().get(cap.getNamespace())
                        + " "
                        + getVersionFromCapability(cap)
                        + " "
                        + UNUSED_MESSAGE);
                }
                else
                {
                    System.out.println(cap + " " + UNUSED_MESSAGE);
                }
            }
        }
        return matches;
    }

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

    static boolean printServiceCapabilities(Bundle b)
    {
        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".
                    System.out.println(
                        NONSTANDARD_SERVICE_NAMESPACE
                        + "; "
                        + Util.getValueString(ref.getProperty("objectClass"))
                        + " with properties:");
                    // Print service properties.
                    String[] keys = ref.getPropertyKeys();
                    for (String key : keys)
                    {
                        if (!key.equalsIgnoreCase(Constants.OBJECTCLASS))
                        {
                            Object v = ref.getProperty(key);
                            System.out.println("   "
                                + key + " = " + Util.getValueString(v));
                        }
                    }
                    Bundle[] users = ref.getUsingBundles();
                    if ((users != null) && (users.length > 0))
                    {
                        System.out.println("   Used by:");
                        for (Bundle user : users)
                        {
                            System.out.println("      " + user);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            System.err.println(ex.toString());
        }

        return matches;
    }

    public static void printRequirements(
        BundleContext bc, List<String> namespace, Bundle[] bundles)
    {
        boolean separatorNeeded = false;
        for (Bundle b : bundles)
        {
            if (separatorNeeded)
            {
                System.out.println("");
            }

            // Print out any matching generic requirements.
            BundleWiring wiring = b.adapt(BundleWiring.class);
            if (wiring != null)
            {
                String title = b + " requires:";
                System.out.println(title);
                System.out.println(Util.getUnderlineString(title.length()));
                boolean matches = printMatchingRequirements(wiring, namespace);

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

                // If there were no requirements for the specified namespace,
                // then say so.
                if (!matches)
                {
                    System.out.println(Util.unparseSubstring(namespace) + " " + EMPTY_MESSAGE);
                }
            }
            else
            {
                System.out.println("Bundle "
                    + b.getBundleId()
                    + " is not resolved.");
            }

            separatorNeeded = true;
        }
    }

    private static boolean printMatchingRequirements(BundleWiring wiring, List<String> namespace)
    {
        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)
                {
                    System.out.println(
                        req.getNamespace()
                        + "; "
                        + req.getDirectives().get(Constants.FILTER_DIRECTIVE)
                        + " resolved by:");
                    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();
                        }
                        msg = "   " + msg + " from "
                            + wire.getProviderWiring().getBundle();
                        System.out.println(msg);
                    }
                }
                else
                {
                    System.out.println(
                        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<BundleRequirement, List<BundleWire>>();
        for (BundleWire wire : wires)
        {
            if (matchNamespace(namespace, wire.getRequirement().getNamespace()))
            {
                List<BundleWire> providers = map.get(wire.getRequirement());
                if (providers == null)
                {
                    providers = new ArrayList<BundleWire>();
                    map.put(wire.getRequirement(), providers);
                }
                providers.add(wire);
            }
        }
        return map;
    }

    static boolean printServiceRequirements(Bundle b)
    {
        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".
                    System.out.println(
                        NONSTANDARD_SERVICE_NAMESPACE
                        + "; "
                        + Util.getValueString(ref.getProperty("objectClass"))
                        + " provided by:");
                    System.out.println("   " + 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));
    }

    private static boolean isFragment(Bundle bundle)
    {
        return bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null;
    }
}