/*
 * Licensed 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.karaf.subsystem.commands;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import org.apache.felix.utils.manifest.Attribute;
import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.manifest.Directive;
import org.apache.felix.utils.manifest.Parser;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.api.console.Terminal;
import org.apache.karaf.shell.support.ShellUtil;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.SubsystemConstants;

@Command(scope = "subsystem", name = "info", description = "Display information about subsystems")
@Service
public class InfoAction extends SubsystemSupport implements Action {

    protected final static String SUBSYSTEM_PREFIX = "Subsystem-";
    protected final static String PACKAGE_SUFFFIX = "-Package";
    protected final static String SERVICE_SUFFIX = "-Service";
    protected final static String CAPABILITY_SUFFIX = "-Capability";
    protected final static String IMPORT_PACKAGES_ATTRIB = "Import-Package";
    protected final static String REQUIRE_BUNDLE_ATTRIB = "Require-Bundle";

    @Option(name = "--indent", description = "Indentation method")
    int indent = -1;

    @Argument(description = "Subsystem names or ids")
    @Completion(SubsystemCompleter.class)
    String id;

    @Reference(optional = true)
    Terminal terminal;

    @Override
    public Object execute() throws Exception {
        for (Subsystem ss : getSubsystems(id)) {
            printHeaders(ss);
        }
        return null;
    }

    protected void printHeaders(Subsystem subsystem) throws Exception {
        String title = getSubsystemName(subsystem);
        System.out.println("\n" + title);
        System.out.println(ShellUtil.getUnderlineString(title));
        if (indent == 0) {
            Map<String, String> dict = subsystem.getSubsystemHeaders(null);
            for (String k : dict.keySet()) {
                Object v = dict.get(k);
                System.out.println(k + " = " + ShellUtil.getValueString(v));
            }
        } else {
            System.out.println(generateFormattedOutput(subsystem));
        }
    }

    public static String getSubsystemName(Subsystem subsystem) {
        String name = subsystem.getSubsystemHeaders(null).get(SubsystemConstants.SUBSYSTEM_NAME);
        return (name == null)
                ? "Subsystem " + Long.toString(subsystem.getSubsystemId())
                : name + " (" + Long.toString(subsystem.getSubsystemId()) + ")";
    }

    protected String generateFormattedOutput(Subsystem subsystem) {
        StringBuilder output = new StringBuilder();
        Map<String, Object> otherAttribs = new TreeMap<String, Object>();
        Map<String, Object> subsystemAttribs = new TreeMap<String, Object>();
        Map<String, Object> serviceAttribs = new TreeMap<String, Object>();
        Map<String, Object> packagesAttribs = new TreeMap<String, Object>();
        Map<String, String> dict = subsystem.getSubsystemHeaders(null);

        // do an initial loop and separate the attributes in different groups
        for (String k : dict.keySet()) {
            Object v = dict.get(k);
            if (k.startsWith(SUBSYSTEM_PREFIX)) {
                // starts with Bundle-xxx
                subsystemAttribs.put(k, v);
            } else if (k.endsWith(SERVICE_SUFFIX) || k.endsWith(CAPABILITY_SUFFIX)) {
                // ends with xxx-Service
                serviceAttribs.put(k, v);
            } else if (k.endsWith(PACKAGE_SUFFFIX)) {
                // ends with xxx-Package
                packagesAttribs.put(k, v);
            } else if (k.endsWith(REQUIRE_BUNDLE_ATTRIB)) {
                // require bundle statement
                packagesAttribs.put(k, v);
            } else {
                // the remaining attribs
                otherAttribs.put(k, v);
            }
        }

        // we will display the formatted result like this:
        // Bundle-Name (ID)
        // -----------------------
        // all other attributes
        //
        // all Subsystem attributes
        //
        // all Service attributes
        //
        // all Package attributes
        Iterator<Map.Entry<String, Object>> it = otherAttribs.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> e = it.next();
            output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
        }
        if (otherAttribs.size() > 0) {
            output.append('\n');
        }

        it = subsystemAttribs.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> e = it.next();
            output.append(e.getKey());
            output.append(" = \n");
            formatHeader(ShellUtil.getValueString(e.getValue()), null, output, indent);
            output.append("\n");
        }
        if (subsystemAttribs.size() > 0) {
            output.append('\n');
        }

        it = serviceAttribs.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> e = it.next();
            output.append(e.getKey());
            output.append(" = \n");
            formatHeader(ShellUtil.getValueString(e.getValue()), null, output, indent);
            output.append("\n");
        }
        if (serviceAttribs.size() > 0) {
            output.append('\n');
        }

        Map<String, ClauseFormatter> formatters = new HashMap<String, ClauseFormatter>();
        /*
        formatters.put(REQUIRE_BUNDLE_ATTRIB, new ClauseFormatter() {
            public void pre(Clause clause, StringBuilder output) {
                boolean isSatisfied = checkBundle(clause.getName(), clause.getAttribute("bundle-version"));
                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED).a("");
            }
            public void post(Clause clause, StringBuilder output) {
                Ansi.ansi(output).reset().a("");
            }
        });
        formatters.put(IMPORT_PACKAGES_ATTRIB, new ClauseFormatter() {
            public void pre(Clause clause, StringBuilder output) {
                boolean isSatisfied = checkPackage(clause.getName(), clause.getAttribute("version"));
                boolean isOptional = "optional".equals(clause.getDirective("resolution"));
                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED)
                        .a(isSatisfied || isOptional ? Ansi.Attribute.INTENSITY_BOLD_OFF : Ansi.Attribute.INTENSITY_BOLD)
                        .a("");
            }
            public void post(Clause clause, StringBuilder output) {
                Ansi.ansi(output).reset().a("");
            }
        });
        */

        it = packagesAttribs.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> e = it.next();
            output.append(e.getKey());
            output.append(" = \n");
            formatHeader(ShellUtil.getValueString(e.getValue()), formatters.get(e.getKey()), output, indent);
            output.append("\n");
        }
        if (packagesAttribs.size() > 0) {
            output.append('\n');
        }

        return output.toString();
    }

    protected interface ClauseFormatter {
        void pre(Clause clause, StringBuilder output);
        void post(Clause clause, StringBuilder output);
    }

    protected void formatHeader(String header, ClauseFormatter formatter, StringBuilder builder, int indent) {
        Clause[] clauses = Parser.parseHeader(header);
        formatClauses(clauses, formatter, builder, indent);
    }

    protected void formatClauses(Clause[] clauses, ClauseFormatter formatter, StringBuilder builder, int indent) {
        boolean first = true;
        for (Clause clause : clauses) {
            if (first) {
                first = false;
            } else {
                builder.append(",\n");
            }
            formatClause(clause, formatter, builder, indent);
        }
    }

    protected void formatClause(Clause clause, ClauseFormatter formatter, StringBuilder builder, int indent) {
        builder.append("\t");
        if (formatter != null) {
            formatter.pre(clause, builder);
        }
        formatClause(clause, builder, indent);
        if (formatter != null) {
            formatter.post(clause, builder);
        }
    }

    protected int getTermWidth() {
        return terminal != null ? terminal.getWidth() : 80;

    }

    protected void formatClause(Clause clause, StringBuilder builder, int indent) {
        if (indent < 0) {
            if (clause.toString().length() < getTermWidth() - 8) { // -8 for tabs
                indent = 1;
            } else {
                indent = 3;
            }
        }
        String name = clause.getName();
        Directive[] directives = clause.getDirectives();
        Attribute[] attributes = clause.getAttributes();
        Arrays.sort(directives, new Comparator<Directive>() {
            public int compare(Directive o1, Directive o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        Arrays.sort(attributes, new Comparator<Attribute>() {
            public int compare(Attribute o1, Attribute o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });
        builder.append(name);
        for (int i = 0; directives != null && i < directives.length; i++) {
            builder.append(";");
            if (indent > 1) {
                builder.append("\n\t\t");
            }
            builder.append(directives[i].getName()).append(":=");
            String v = directives[i].getValue();
            if (v.contains(",")) {
                if (indent > 2 && v.length() > 20) {
                    v = v.replace(",", ",\n\t\t\t");
                }
                builder.append("\"").append(v).append("\"");
            } else {
                builder.append(v);
            }
        }
        for (int i = 0; attributes != null && i < attributes.length; i++) {
            builder.append(";");
            if (indent > 1) {
                builder.append("\n\t\t");
            }
            builder.append(attributes[i].getName()).append("=");
            String v = attributes[i].getValue();
            if (v.contains(",")) {
                if (indent > 2 && v.length() > 20) {
                    v = v.replace(",", ",\n\t\t\t");
                }
                builder.append("\"").append(v).append("\"");
            } else {
                builder.append(v);
            }
        }
    }


    /*
    private boolean checkBundle(String bundleName, String version) {
        VersionRange vr = VersionRange.parseVersionRange(version);
        Bundle[] bundles = bundleContext.getBundles();
        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
            String sym = bundles[i].getSymbolicName();
            if ((sym != null) && sym.equals(bundleName)) {
                if (vr.contains(bundles[i].getVersion())) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean checkPackage(String packageName, String version) {
        VersionRange range = VersionRange.parseVersionRange(version);
        Bundle[] bundles = bundleContext.getBundles();
        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
            BundleWiring wiring = bundles[i].adapt(BundleWiring.class);
            List<BundleCapability> caps = wiring != null ? wiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE) : null;
            if (caps != null) {
                for (BundleCapability cap : caps) {
                    String n = getAttribute(cap, BundleRevision.PACKAGE_NAMESPACE);
                    String v = getAttribute(cap, Constants.VERSION_ATTRIBUTE);
                    if (packageName.equals(n) && range.contains(VersionTable.getVersion(v))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private String getAttribute(BundleCapability cap, String name)  {
        Object obj = cap.getAttributes().get(name);
        return obj != null ? obj.toString() : null;
    }
    */

}
