/*
 * 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 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.builder.BuilderContext;
import org.apache.sling.feature.builder.FeatureBuilder;
import org.apache.sling.feature.builder.FeatureProvider;
import org.apache.sling.feature.io.json.FeatureJSONReader;
import org.apache.sling.provisioning.model.Artifact;
import org.apache.sling.provisioning.model.Configuration;
import org.apache.sling.provisioning.model.Feature;
import org.apache.sling.provisioning.model.Model;
import org.apache.sling.provisioning.model.Section;
import org.apache.sling.provisioning.model.io.ModelWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonValue;

/** Converter that converts the feature model to the provisioning model.
 */
public class FeatureToProvisioning {
    private static final Logger LOGGER = LoggerFactory.getLogger(FeatureToProvisioning.class);
    static final String PROVISIONING_MODEL_NAME_VARIABLE = "provisioning.model.name";
    static final String PROVISIONING_RUNMODES = "provisioning.runmodes";

    public static void convert(File inputFile, File outputFile, FeatureProvider fp, File ... additionalInputFiles) throws UncheckedIOException {
        if (outputFile.exists()) {
            if (outputFile.lastModified() > inputFile.lastModified()) {
                LOGGER.debug("Skipping the generation of {} as this file already exists and is newer.", outputFile);
                return;
            }
        }

        org.apache.sling.feature.Feature feature = getFeature(inputFile);
        if (feature.getInclude() != null) {
            feature = handleIncludes(feature, additionalInputFiles, fp);
        }

        Object featureNameVar = feature.getVariables().remove(PROVISIONING_MODEL_NAME_VARIABLE);
        String featureName;
        if (featureNameVar instanceof String) {
            featureName = (String) featureNameVar;
        } else {
            featureName = feature.getId().getArtifactId();
        }

        String runMode = feature.getVariables().remove(PROVISIONING_RUNMODES);
        String[] runModes = null;
        if (runMode != null) {
            runModes = runMode.split(",");
        }

        Feature newFeature = new Feature(featureName);
        convert(newFeature, feature.getVariables(), feature.getBundles(), feature.getConfigurations(),
                feature.getFrameworkProperties(), feature.getExtensions(), outputFile.getAbsolutePath(), runModes);
    }

    static org.apache.sling.feature.Feature getFeature(final File file) throws UncheckedIOException {
        try (final Reader r = new InputStreamReader(new FileInputStream(file), "UTF-8")) {
            return FeatureJSONReader.read(r, file.toURI().toURL().toString());
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }

    }

    private static org.apache.sling.feature.Feature handleIncludes(org.apache.sling.feature.Feature feature, File[] additionalFiles, FeatureProvider fp) throws UncheckedIOException {
        Map<ArtifactId, org.apache.sling.feature.Feature> features =
            Stream.of(additionalFiles)
                .map(FeatureToProvisioning::getFeature)
                .collect(Collectors.toMap(org.apache.sling.feature.Feature::getId, Function.identity()));

        BuilderContext bc = new BuilderContext(id -> features.containsKey(id) ? features.get(id) : fp.provide(id));

        return FeatureBuilder.assemble(feature, bc);
    }

    private static void convert(Feature f, Map<String,String> variables, Bundles bundles, Configurations configurations, Map<String,String> frameworkProps,
            Extensions extensions, String outputFile, String [] runModes) {
        final Map<String, Feature> additionalFeatures = new HashMap<>();

        if (runModes != null && runModes.length == 0) {
            runModes = null;
        }
        org.apache.sling.provisioning.model.KeyValueMap<String> vars = f.getVariables();
        for (Map.Entry<String, String> entry : variables.entrySet()) {
            vars.put(entry.getKey(), entry.getValue());
        }

        Map<org.apache.sling.feature.Configuration, org.apache.sling.feature.Artifact> configBundleMap = new HashMap<>();

        // bundles
        for(final org.apache.sling.feature.Artifact bundle : bundles) {
            final ArtifactId id = bundle.getId();
            final Artifact newBundle = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());

            Object configs = bundle.getMetadata().get("configurations");
            if (configs instanceof List) {
                for (Object config : (List<?>) configs) {
                    if (config instanceof org.apache.sling.feature.Configuration) {
                        configBundleMap.put((org.apache.sling.feature.Configuration) config, bundle);
                    }
                }
            }

            for(final Map.Entry<String, String> prop : bundle.getMetadata().entrySet()) {
                switch (prop.getKey()) {
                    // these are handled separately
                    case "start-level":
                    case "run-modes":
                        break;
                    default:
                        newBundle.getMetadata().put(prop.getKey(), prop.getValue());
                }
            }

            String[] bundleRunModes = runModes;
            if (bundleRunModes == null) {
                bundleRunModes = getRunModes(bundle);
            }

            int startLevel;
            String sl = bundle.getMetadata().get("start-level");
            // special handling for :boot or :launchpad
            if ( sl != null && sl.startsWith(":") ) {
                if ( bundleRunModes != null ) {
                    LOGGER.error("Unable to convert feature {}. Run modes must not be defined for bundles with start-level {}", f.getName(), sl);
                    System.exit(1);
                }

                Feature addFeat = additionalFeatures.get(sl);
                if ( addFeat == null ) {
                    addFeat = new Feature(sl);
                    additionalFeatures.put(sl, addFeat);
                }
                addFeat.getOrCreateRunMode(null).getOrCreateArtifactGroup(0).add(newBundle);
            } else {
                if (sl != null) {
                    startLevel = Integer.parseInt(sl);
                } else {
                    startLevel = 20;
                }

                f.getOrCreateRunMode(bundleRunModes).getOrCreateArtifactGroup(startLevel).add(newBundle);
            }
        }

        // configurations
        for(final org.apache.sling.feature.Configuration cfg : configurations) {
            final Configuration c;

            List<String> runModeList = new ArrayList<>();
            if ( cfg.isFactoryConfiguration() ) {
                String name = decodeRunModes(cfg.getName(), runModeList);
                c = new Configuration(name, cfg.getFactoryPid());
            } else {
                String pid = decodeRunModes(cfg.getPid(), runModeList);
                c = new Configuration(pid, null);
            }
            final Enumeration<String> keys = cfg.getProperties().keys();
            while ( keys.hasMoreElements() ) {
                String key = keys.nextElement();
                Object val = cfg.getProperties().get(key);

                if (key.startsWith("..")) {
                    key = ":" + key.substring(2);
                }
                c.getProperties().put(key, val);
            }
            String[] cfgRunModes = runModes;
            if (cfgRunModes == null) {
                cfgRunModes = runModeList.toArray(new String[] {});
                if (cfgRunModes.length == 0)
                    cfgRunModes = null;
            }
            f.getOrCreateRunMode(cfgRunModes).getConfigurations().add(c);
        }

        // framework properties
        for(final Map.Entry<String, String> prop : frameworkProps.entrySet()) {
            String key = prop.getKey();
            int idx = key.indexOf(".runmodes:");

            if (idx > 0) {
                String rm = key.substring(idx + ".runmodes:".length());
                String[] runmodes = rm.split(",");
                key = key.substring(0, idx);
                f.getOrCreateRunMode(runmodes).getSettings().put(key, prop.getValue());
            } else {
                f.getOrCreateRunMode(null).getSettings().put(key, prop.getValue());
            }
        }

        // extensions: content packages and repoinit
        for(final Extension ext : extensions) {
            if ( FeatureConstants.EXTENSION_NAME_CONTENT_PACKAGES.equals(ext.getName()) ) {
                for(final org.apache.sling.feature.Artifact cp : ext.getArtifacts() ) {
                    String[] extRunModes = runModes;
                    final ArtifactId id = cp.getId();
                    final Artifact newCP = new Artifact(id.getGroupId(), id.getArtifactId(), id.getVersion(), id.getClassifier(), id.getType());
                    for(final Map.Entry<String, String> prop : cp.getMetadata().entrySet()) {
                        if (prop.getKey().equals("runmodes")) {
                            if (extRunModes == null) {
                                extRunModes = prop.getValue().split(",");
                            }
                        } else {
                            newCP.getMetadata().put(prop.getKey(), prop.getValue());
                        }
                    }
                    f.getOrCreateRunMode(extRunModes).getOrCreateArtifactGroup(20).add(newCP);
                }

            } else if ( FeatureConstants.EXTENSION_NAME_REPOINIT.equals(ext.getName()) ) {
                final Section section = new Section("repoinit");
                if (ext.getType() == ExtensionType.TEXT) {
                    section.setContents(ext.getText());
                } else if (ext.getType() == ExtensionType.JSON) {
                    JsonReader reader = Json.createReader(new StringReader(ext.getJSON()));
                    JsonArray arr = reader.readArray();
                    StringBuilder sb = new StringBuilder();
                    for (JsonValue v : arr) {
                        if (v instanceof JsonString) {
                            sb.append(((JsonString) v).getString());
                            sb.append('\n');
                        }
                    }
                    section.setContents(sb.toString());
                }
                f.getAdditionalSections().add(section);
            } else if ( ext.isRequired() ) {
                LOGGER.error("Unable to convert required extension {}", ext.getName());
                System.exit(1);
            }
        }

        final String out = outputFile;
        final File file = new File(out);
        final Model m = new Model();
        m.getFeatures().add(f);
        for(final Feature addFeat : additionalFeatures.values()) {
            m.getFeatures().add(addFeat);
        }
        try ( final FileWriter writer = new FileWriter(file)) {
            ModelWriter.write(writer, m);
        } catch ( final IOException ioe) {
            LOGGER.error("Unable to write feature to {} : {}", out, ioe.getMessage(), ioe);
            System.exit(1);
        }
    }

    private static String decodeRunModes(String pid, List<String> runModes) {
        pid = pid.replaceAll("[.][.](\\w+)", ":$1");
        int rmIdx = pid.indexOf(".runmodes.");
        if (rmIdx > 0) {
            String rm = pid.substring(rmIdx + ".runmodes.".length());
            pid = pid.substring(0, rmIdx);
            runModes.addAll(Arrays.asList(rm.split("[.]")));
        }
        return pid;
    }

    private static String[] getRunModes(final org.apache.sling.feature.Artifact bundle) {
        String runMode = bundle.getMetadata().get("run-modes");
        String[] runModes;
        if (runMode != null) {
            runModes = runMode.split(",");
        } else {
            runModes = null;
        }
        return runModes;
    }
}
