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

import java.util.LinkedList;
import java.util.List;

import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.Conditional;
import org.apache.karaf.features.ConfigFileInfo;
import org.apache.karaf.features.ConfigInfo;
import org.apache.karaf.features.Dependency;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.command.completers.AllFeatureCompleter;
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.Service;

@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
@Service
public class InfoFeatureCommand extends FeaturesCommandSupport {

    private static final String INDENT = "  ";
    private static final String FEATURE_CONTENT = "Feature";
    private static final String CONDITIONAL_CONTENT = "Conditional(%s)";

    @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
    @Completion(AllFeatureCompleter.class)
    private String name;

    @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
    private String version;

    @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false)
    private boolean config;

    @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false)
    private boolean dependency;

    @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
    private boolean bundle;

    @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
    private boolean conditional;

    @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
    private boolean tree;

    protected void doExecute(FeaturesService admin) throws Exception {
        Feature[] features = null;

        if (version != null && version.length() > 0) {
            features = admin.getFeatures(name, version);
        } else {
            features = admin.getFeatures(name);
        }

        if (features == null || features.length == 0) {
            System.out.println("Feature not found");
            return;
        }

        // default behavior
        if (!config && !dependency && !bundle && !conditional) {
            config = true;
            dependency = true;
            bundle = true;
            conditional = true;
        }

        boolean first = true;
        for (Feature feature : features) {
            if (first) {
                first = false;
            } else {
                System.out.println("------------------------------------");
            }
            System.out.println("Feature " + feature.getName() + " " + feature.getVersion());
            if (feature.getDescription() != null) {
                System.out.println("Description:");
                System.out.println(INDENT + feature.getDescription());
            }

            if (feature.getDetails() != null) {
                System.out.println("Details:");
                printWithIndent(feature.getDetails());
            }

            if (config) {
                displayConfigInformation(feature, FEATURE_CONTENT);
                displayConfigFileInformation(feature, FEATURE_CONTENT);
            }

            if (dependency) {
                displayDependencyInformation(feature, FEATURE_CONTENT);
            }

            if (bundle) {
                displayBundleInformation(feature, FEATURE_CONTENT);
            }

            if (conditional) {
                displayConditionalInfo(feature);
            }

            if (tree) {
                if (config || dependency || bundle) {
                    System.out.println("\nFeature tree");
                }

                int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
                if (unresolved > 0) {
                    System.out.println("Tree contains " + unresolved + " unresolved dependencies");
                    System.out.println(" * means that node declares dependency but the dependent feature is not available.");
                }
            }
        }
    }

    private void printWithIndent(String details) {
    	String[] lines = details.split("\r?\n");
    	for (String line : lines) {
			System.out.println(INDENT + line);
		}
	}

	private void displayBundleInformation(Feature feature, String contentType) {
        List<BundleInfo> bundleInfos = feature.getBundles();
        if (bundleInfos.isEmpty()) {
            System.out.println(contentType + " has no bundles.");
        } else {
            System.out.println(contentType + " contains followed bundles:");
            for (BundleInfo featureBundle : bundleInfos) {
                int startLevel = featureBundle.getStartLevel();
                StringBuilder sb = new StringBuilder();
                sb.append(INDENT).append(featureBundle.getLocation());
                if(startLevel > 0) {
                    sb.append(" start-level=").append(startLevel);
                }
                System.out.println(sb.toString());
            }
        }
    }

    private void displayDependencyInformation(Feature feature, String contentType) {
        List<Dependency> dependencies = feature.getDependencies();
        if (dependencies.isEmpty()) {
            System.out.println(contentType + " has no dependencies.");
        } else {
            System.out.println(contentType + " depends on:");
            for (Dependency featureDependency : dependencies) {
                System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
            }
        }
    }

    private void displayConfigInformation(Feature feature, String contentType) {
		List<ConfigInfo> configurations = feature.getConfigurations();
        if (configurations.isEmpty()) {
            System.out.println(contentType + " has no configuration");
        } else {
            System.out.println(contentType + " configuration:");
			for (ConfigInfo configInfo : configurations) {
				System.out.println(INDENT + configInfo.getName());
            }
        }
    }
    
    private void displayConfigFileInformation(Feature feature, String contentType) {
    	List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
    	if (configurationFiles.isEmpty()) {
    		System.out.println(contentType + " has no configuration files");
    	} else {
    		System.out.println(contentType + " configuration files: ");
    		for (ConfigFileInfo configFileInfo : configurationFiles) {
				System.out.println(INDENT + configFileInfo.getFinalname());
			}
    	}    	
    }

    /**
     * Called originally with featureName and featureVersion that have already been resolved successfully.
     *
     * @param admin
     * @param featureName
     * @param featureVersion
     * @param prefix
     * @return
     * @throws Exception
     */
    private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
        int unresolved = 0;

        Feature[] resolvedFeatures = admin.getFeatures(featureName, featureVersion);
        for (Feature resolved:resolvedFeatures) {
            if (resolved != null) {
                System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
            } else {
                System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
                unresolved++;
            }

            if (resolved != null) {
                if (bundle) {
                    List<String> bundleLocation = new LinkedList<String>();
                    List<BundleInfo> bundles = resolved.getBundles();
                    for (BundleInfo bundleInfo : bundles) {
                        bundleLocation.add(bundleInfo.getLocation());
                    }

                    if (conditional) {
                        for (Conditional cond : resolved.getConditional()) {
                            List<String> condition = cond.getCondition();
                            List<BundleInfo> conditionalBundles = cond.getBundles();
                            for (BundleInfo bundleInfo : conditionalBundles) {
                                bundleLocation.add(bundleInfo.getLocation() + "(condition:" + condition + ")");
                            }
                        }
                    }
                    for (int i = 0, j = bundleLocation.size(); i < j; i++) {
                        System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
                    }
                }
                prefix += "   ";
                List<Dependency> dependencies = resolved.getDependencies();
                for (int i = 0, j = dependencies.size(); i < j; i++) {
                    Dependency toDisplay = dependencies.get(i);
                    unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix + 1);
                }

                if (conditional) {
                    for (Conditional cond : resolved.getConditional()) {
                        List<Dependency> conditionDependencies = cond.getDependencies();
                        for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
                            Dependency toDisplay = dependencies.get(i);
                            unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix + 1);
                        }
                    }
                }
            }
        }

        return unresolved;
    }

    private void displayConditionalInfo(Feature feature) {
        List<? extends Conditional> conditionals = feature.getConditional();
        if (conditionals.isEmpty()) {
            System.out.println("Feature has no conditionals.");
        } else {
            System.out.println("Feature contains followed conditionals:");
            for (Conditional featureConditional : conditionals) {
                String conditionDescription = getConditionDescription(featureConditional);
                Feature wrappedConditional = featureConditional.asFeature();
                if (config) {
                    displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
                    displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
                }

                if (dependency) {
                    displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
                }

                if (bundle) {
                    displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
                }
            }
        }
    }

    private String getConditionDescription(Conditional cond) {
        StringBuffer sb = new StringBuffer();
        for (String dep : cond.getCondition()) {
            if (sb.length() > 0) {
                sb.append(" ");
            }
            sb.append(dep);
        }
        return sb.toString();
    }

}
