/*
 * 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.sling.feature.modelconverter;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Bundles;
import org.apache.sling.feature.Configurations;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Extensions;
import org.apache.sling.feature.FeatureConstants;
import org.apache.sling.feature.KeyValueMap;
import org.apache.sling.feature.io.file.ArtifactHandler;
import org.apache.sling.feature.io.file.ArtifactManager;
import org.apache.sling.feature.io.file.ArtifactManagerConfig;
import org.apache.sling.feature.io.json.FeatureJSONWriter;
import org.apache.sling.provisioning.model.Artifact;
import org.apache.sling.provisioning.model.ArtifactGroup;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.MergeUtility;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.ModelConstants;
import org.apache.sling.provisioning.model.ModelUtility;
import org.apache.sling.provisioning.model.ModelUtility.ResolverOptions;
import org.apache.sling.provisioning.model.ModelUtility.VariableResolver;
import org.apache.sling.provisioning.model.RunMode;
import org.apache.sling.provisioning.model.Section;
import org.apache.sling.provisioning.model.Traceable;
import org.apache.sling.provisioning.model.io.ModelReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Converter that converts the provisioning model to the feature model.
 */
public class ProvisioningToFeature {
    private static Logger LOGGER = LoggerFactory.getLogger(ProvisioningToFeature.class);

    public static List<File> convert(File file, File outDir, Map<String, Object> options) {
        Model model = createModel(Collections.singletonList(file), null, true, false);

        String bareFileName = getBareFileName(file);
        final List<org.apache.sling.feature.Feature> features = buildFeatures(model, bareFileName, options);

        List<File> files = new ArrayList<>();
        for (org.apache.sling.feature.Feature f : features) {
            String id = f.getVariables().get(FeatureToProvisioning.PROVISIONING_MODEL_NAME_VARIABLE);
            if (id == null) {
                id = f.getId().getArtifactId();
            }
            id = id.replaceAll("[:]","");
            id = bareFileName + "_" + id;

            File outFile = new File(outDir, id + ".json");
            files.add(outFile);

            if (outFile.exists()) {
                if (outFile.lastModified() > file.lastModified()) {
                    LOGGER.debug("Skipping the generation of {} as this file already exists and is newer.", outFile);
                    continue;
                } else {
                    LOGGER.debug("Deleting existing file {} as source is newer", outFile);
                    outFile.delete();
                }
            }

            writeFeature(f, outFile.getAbsolutePath(), 0);
        }
        return files;
    }

    public static void convert(List<File> files,  String outputFile, String runModes, boolean createApp,
            boolean includeModelInfo, String propsFile) {
        final Model model = createModel(files, runModes, false, includeModelInfo);

        final List<org.apache.sling.feature.Feature> features = buildFeatures(model, null, Collections.emptyMap());
        int index = 1;
        for(final org.apache.sling.feature.Feature feature : features) {
            writeFeature(feature, outputFile, features.size() > 1 ? index : 0);
            index++;
        }
    }

    /**
     * Read the models and prepare the model
     * @param files The model files
     * @param includeModelInfo
     */
    private static Model createModel(final List<File> files,
            final String runModes, boolean allRunModes, boolean includeModelInfo) {
        LOGGER.info("Assembling model...");
        ResolverOptions variableResolver = new ResolverOptions().variableResolver(new VariableResolver() {
            @Override
            public String resolve(final Feature feature, final String name) {
                // Keep variables as-is in the model
                return "${" + name + "}";
            }
        });

        Model model = null;
        for(final File initFile : files) {
            try {
                model = processModel(model, initFile, includeModelInfo, variableResolver);
            } catch ( final IOException iae) {
                LOGGER.error("Unable to read provisioning model {} : {}", initFile, iae.getMessage(), iae);
                System.exit(1);
            }
        }

        final Model effectiveModel = ModelUtility.getEffectiveModel(model, variableResolver);
        final Map<Traceable, String> errors = ModelUtility.validate(effectiveModel);
        if ( errors != null ) {
            LOGGER.error("Invalid assembled provisioning model.");
            for(final Map.Entry<Traceable, String> entry : errors.entrySet()) {
                LOGGER.error("- {} : {}", entry.getKey().getLocation(), entry.getValue());
            }
            System.exit(1);
        }
        final Set<String> modes;
        if (allRunModes) {
            modes = new HashSet<>();
            for (Feature f : effectiveModel.getFeatures()) {
                for (RunMode rm : f.getRunModes()) {
                    String[] names = rm.getNames();
                    if (names != null) {
                        modes.addAll(Arrays.asList(names));
                    }
                }
            }
        } else {
            modes = calculateRunModes(effectiveModel, runModes);
        }

        return effectiveModel;
    }

    /**
     * Process the given model and merge it into the provided model
     * @param model The already read model
     * @param modelFile The model file
     * @param includeModelInfo
     * @return The merged model
     * @throws IOException If reading fails
     */
    private static Model processModel(Model model,
            File modelFile, boolean includeModelInfo) throws IOException {
        return processModel(model, modelFile, includeModelInfo,
            new ResolverOptions().variableResolver(new VariableResolver() {
                @Override
                public String resolve(final Feature feature, final String name) {
                    return name;
                }
            })
        );
    }

    private static Model processModel(Model model,
            File modelFile, boolean includeModelInfo, ResolverOptions options) throws IOException {
        LOGGER.info("- reading model {}", modelFile);

        final Model nextModel = readProvisioningModel(modelFile);

        final Model effectiveModel = ModelUtility.getEffectiveModel(nextModel, options);
        for(final Feature feature : effectiveModel.getFeatures()) {
            for(final RunMode runMode : feature.getRunModes()) {
                for(final ArtifactGroup group : runMode.getArtifactGroups()) {
                    final List<org.apache.sling.provisioning.model.Artifact> removeList = new ArrayList<>();
                    for(final org.apache.sling.provisioning.model.Artifact a : group) {
                        if ( "slingstart".equals(a.getType())
                             || "slingfeature".equals(a.getType())) {

                            final ArtifactManagerConfig cfg = new ArtifactManagerConfig();
                            final ArtifactManager mgr = ArtifactManager.getArtifactManager(cfg);

                            final ArtifactId correctedId = new ArtifactId(a.getGroupId(),
                                    a.getArtifactId(),
                                    a.getVersion(),
                                    "slingstart".equals(a.getType()) ? "slingfeature" : a.getClassifier(),
                                    "txt");

                            final ArtifactHandler handler = mgr.getArtifactHandler(correctedId.toMvnUrl());
                            model = processModel(model, handler.getFile(), includeModelInfo);

                            removeList.add(a);
                        } else {
                            final org.apache.sling.provisioning.model.Artifact realArtifact = nextModel.getFeature(feature.getName()).getRunMode(runMode.getNames()).getArtifactGroup(group.getStartLevel()).search(a);

                            if ( includeModelInfo ) {
                                realArtifact.getMetadata().put("model-filename", modelFile.getName());
                            }
                            if ( runMode.getNames() != null ) {
                                realArtifact.getMetadata().put("runmodes", String.join(",", runMode.getNames()));
                            }
                        }
                    }
                    for(final org.apache.sling.provisioning.model.Artifact r : removeList) {
                        nextModel.getFeature(feature.getName()).getRunMode(runMode.getNames()).getArtifactGroup(group.getStartLevel()).remove(r);
                    }
                }
            }
        }

        if ( model == null ) {
            model = nextModel;
        } else {
            MergeUtility.merge(model, nextModel);
        }
        return model;
    }

    /**
     * Read the provisioning model
     */
    private static Model readProvisioningModel(final File file)
    throws IOException {
        try (final FileReader is = new FileReader(file)) {
            return ModelReader.read(is, file.getAbsolutePath());
        }
    }

    private static Set<String> calculateRunModes(final Model model, final String runModes) {
        final Set<String> modesSet = new HashSet<>();

        // check configuration property first
        if (runModes != null && runModes.trim().length() > 0) {
            final String[] modes = runModes.split(",");
            for(int i=0; i < modes.length; i++) {
                modesSet.add(modes[i].trim());
            }
        }

        //  handle configured options
        final Feature feature = model.getFeature(ModelConstants.FEATURE_BOOT);
        if ( feature != null ) {
            handleOptions(modesSet, feature.getRunMode().getSettings().get("sling.run.mode.options"));
            handleOptions(modesSet, feature.getRunMode().getSettings().get("sling.run.mode.install.options"));
        }

        return modesSet;
    }

    private static void handleOptions(final Set<String> modesSet, final String propOptions) {
        if ( propOptions != null && propOptions.trim().length() > 0 ) {

            final String[] options = propOptions.trim().split("\\|");
            for(final String opt : options) {
                String selected = null;
                final String[] modes = opt.trim().split(",");
                for(int i=0; i<modes.length; i++) {
                    modes[i] = modes[i].trim();
                    if ( selected != null ) {
                        modesSet.remove(modes[i]);
                    } else {
                        if ( modesSet.contains(modes[i]) ) {
                            selected = modes[i];
                        }
                    }
                }
                if ( selected == null ) {
                    selected = modes[0];
                    modesSet.add(modes[0]);
                }
            }
        }
    }

    private static void buildFromFeature(final Feature feature,
            final KeyValueMap variables,
            final Bundles bundles,
            final Configurations configurations,
            final Extensions extensions,
            final KeyValueMap properties) {
        for (Iterator<Map.Entry<String, String>> it = feature.getVariables().iterator(); it.hasNext(); ) {
            Entry<String, String> entry = it.next();
            variables.put(entry.getKey(), entry.getValue());
        }

        Extension cpExtension = extensions.getByName(FeatureConstants.EXTENSION_NAME_CONTENT_PACKAGES);
        for(final RunMode runMode : feature.getRunModes() ) {
            for(final ArtifactGroup group : runMode.getArtifactGroups()) {
                for(final Artifact artifact : group) {
                    final ArtifactId id = ArtifactId.fromMvnUrl(artifact.toMvnUrl());
                    final org.apache.sling.feature.Artifact newArtifact = new org.apache.sling.feature.Artifact(id);

                    for(final Map.Entry<String, String> entry : artifact.getMetadata().entrySet()) {
                        newArtifact.getMetadata().put(entry.getKey(), entry.getValue());
                    }

                    if ( newArtifact.getId().getType().equals("zip") ) {
                        if ( cpExtension == null ) {
                            cpExtension = new Extension(ExtensionType.ARTIFACTS, FeatureConstants.EXTENSION_NAME_CONTENT_PACKAGES, true);
                            extensions.add(cpExtension);
                        }
                        cpExtension.getArtifacts().add(newArtifact);
                    } else {
                        int startLevel = group.getStartLevel();
                        if ( startLevel == 0) {
                            if ( ModelConstants.FEATURE_BOOT.equals(feature.getName()) ) {
                                startLevel = 1;
                            } else if ( startLevel == 0 ) {
                                startLevel = 20;
                            }
                        }
                        newArtifact.getMetadata().put("start-level", String.valueOf(startLevel));

                        bundles.add(newArtifact);
                    }
                }
            }

            for(final Configuration cfg : runMode.getConfigurations()) {
                String pid = cfg.getPid();
                if (pid.startsWith(":")) {
                    // The configurator doesn't accept colons ':' in it's keys, so replace these
                    pid = ".." + pid.substring(1);
                }

                final String[] runModeNames = runMode.getNames();
                if (runModeNames != null) {
                    pid = pid + ".runmodes." + String.join(".", runModeNames);
                    pid = pid.replaceAll("[:]", "..");
                }

                final org.apache.sling.feature.Configuration newCfg;
                if ( cfg.getFactoryPid() != null ) {
                    newCfg = new org.apache.sling.feature.Configuration(cfg.getFactoryPid(), pid);
                } else {
                    newCfg = new org.apache.sling.feature.Configuration(pid);
                }
                final Enumeration<String> keys = cfg.getProperties().keys();
                while ( keys.hasMoreElements() ) {
                    String key = keys.nextElement();
                    Object value = cfg.getProperties().get(key);

                    if (key.startsWith(":")) {
                        key = ".." + key.substring(1);
                    }
                    newCfg.getProperties().put(key, value);
                }

                configurations.add(newCfg);
            }

            for(final Map.Entry<String, String> prop : runMode.getSettings()) {
                String[] runModeNames = runMode.getNames();
                if (runModeNames == null) {
                    properties.put(prop.getKey(), prop.getValue());
                } else {
                    properties.put(prop.getKey() + ".runmodes:" + String.join(",", runModeNames),
                            prop.getValue());
                }
            }
        }

        final StringBuilder repoinitText = new StringBuilder();
        for(final Section sect : feature.getAdditionalSections("repoinit")) {
            repoinitText.append(sect.getContents()).append("\n");
        }

        if(repoinitText.length() > 0) {
            Extension repoExtension = extensions.getByName(FeatureConstants.EXTENSION_NAME_REPOINIT);

            if ( repoExtension == null ) {
                repoExtension = new Extension(ExtensionType.JSON, FeatureConstants.EXTENSION_NAME_REPOINIT, true);
                extensions.add(repoExtension);
                repoExtension.setJSON(textToJSON(repoinitText.toString()));
            } else {
                throw new IllegalStateException("Repoinit sections already processed");
            }
        }
}

    private static String textToJSON(String text) {
        text = text.replace('\t', ' ');
        String[] lines = text.split("[\n]");

        StringBuilder sb = new StringBuilder();
        sb.append('[');

        boolean first = true;
        for (String t : lines) {
            if (first)
                first = false;
            else
                sb.append(',');

            sb.append('"');
            sb.append(t);
            sb.append('"');
        }
        sb.append(']');
        return sb.toString();
    }

    private static List<org.apache.sling.feature.Feature> buildFeatures(Model model, String bareFileName, Map<String, Object> options) {
        final List<org.apache.sling.feature.Feature> features = new ArrayList<>();

        String groupId = getOption(options, "groupId", "generated");
        String version = getOption(options, "version", "1.0.0");

        for(final Feature feature : model.getFeatures() ) {
            final String idString;
            String name = feature.getName();
            if ( name != null ) {
                name = name.replaceAll("[:]", "");

                if (!name.equals(bareFileName)) {
                    name = bareFileName + "_" + name;
                }

                if ( feature.getVersion() != null ) {
                    idString = groupId + "/" + name + "/" + feature.getVersion();
                } else {
                    idString = groupId + "/" + name + "/" + version;
                }
            } else {
                idString = groupId + "/feature/" + version;
            }
            final org.apache.sling.feature.Feature f = new org.apache.sling.feature.Feature(ArtifactId.parse(idString));
            features.add(f);

            buildFromFeature(feature, f.getVariables(), f.getBundles(), f.getConfigurations(), f.getExtensions(), f.getFrameworkProperties());

            if (!f.getId().getArtifactId().equals(feature.getName())) {
                f.getVariables().put(FeatureToProvisioning.PROVISIONING_MODEL_NAME_VARIABLE, feature.getName());
            }
        }

        return features;
    }

    private static String getBareFileName(File file) {
        String bareFileName = file.getName();
        int idx = bareFileName.lastIndexOf('.');
        if (idx > 0) {
            bareFileName = bareFileName.substring(0, idx);
        }
        return bareFileName;
    }

    @SuppressWarnings("unchecked")
    private static <T> T getOption(Map<String, Object> options, String name, T defaultValue) {
        if (options.containsKey(name)) {
            return (T) options.get(name);
        } else {
            return defaultValue;
        }
    }

    private static void writeFeature(final org.apache.sling.feature.Feature f, String out, final int index) {
        if ( index > 0 ) {
            final int lastDot = out.lastIndexOf('.');
            if ( lastDot == -1 ) {
                out = out + "_" + String.valueOf(index);
            } else {
                out = out.substring(0, lastDot) + "_" + String.valueOf(index) + out.substring(lastDot);
            }
        }

        LOGGER.info("to file {}", out);
        final File file = new File(out);
        while (file.exists()) {
            LOGGER.error("Output file already exists: {}", file.getAbsolutePath());
            System.exit(1);
        }

        try ( final FileWriter writer = new FileWriter(file)) {
            FeatureJSONWriter.write(writer, f);
        } catch ( final IOException ioe) {
            LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
            System.exit(1);
        }
    }
}
