/*
 * 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.launcher.impl;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.builder.BuilderContext;
import org.apache.sling.feature.builder.FeatureBuilder;
import org.apache.sling.feature.builder.MergeHandler;
import org.apache.sling.feature.builder.PostProcessHandler;
import org.apache.sling.feature.io.IOUtils;
import org.apache.sling.feature.io.artifacts.ArtifactHandler;
import org.apache.sling.feature.io.artifacts.ArtifactManager;
import org.apache.sling.feature.io.json.FeatureJSONReader;
import org.apache.sling.feature.launcher.spi.LauncherPrepareContext;
import org.apache.sling.feature.launcher.spi.extensions.ExtensionHandler;
import org.slf4j.Logger;

public class FeatureProcessor {

    /**
     * Initialize the launcher
     * Read the features and prepare the application
     * @param config The current configuration
     * @param artifactManager The artifact manager
     * @param loadedFeatures This map will be populated with features that were loaded as part of this process
     * @return The merged feature representing the application
     * @throws IOException when an IO exception occurs during application creation
     */
    public static Feature createApplication(final Logger logger, final LauncherConfig config,
            final ArtifactManager artifactManager, final Map<ArtifactId, Feature> loadedFeatures) throws IOException
    {
        final BuilderContext builderContext = new BuilderContext(id -> {
            try {
                final ArtifactHandler handler = artifactManager.getArtifactHandler(id.toMvnUrl());
                try (final Reader r = new InputStreamReader(handler.getLocalURL().openStream(), "UTF-8")) {
                    final Feature f = FeatureJSONReader.read(r, handler.getUrl());
                    return f;
                }
            } catch (IOException e) {
                // ignore
                return null;
            }
        });
        builderContext.setArtifactProvider(id -> {
            try {
                final ArtifactHandler handler = artifactManager.getArtifactHandler(id.toMvnUrl());
                return handler.getLocalURL();
            } catch (final IOException e) {
                // ignore
                return null;
            }
        });
        builderContext.addArtifactsOverrides(config.getArtifactClashOverrides());
        builderContext.addVariablesOverrides(config.getVariables());
        builderContext.addFrameworkPropertiesOverrides(config.getInstallation().getFrameworkProperties());
        builderContext.addMergeExtensions(StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                ServiceLoader.load(MergeHandler.class).iterator(), Spliterator.ORDERED), false)
                    .toArray(MergeHandler[]::new));
        builderContext.addPostProcessExtensions(StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            ServiceLoader.load(PostProcessHandler.class).iterator(), Spliterator.ORDERED), false)
                .toArray(PostProcessHandler[]::new));
        for (Map.Entry<String, Map<String,String>> entry : config.getExtensionConfiguration().entrySet()) {
            builderContext.setHandlerConfiguration(entry.getKey(), entry.getValue());
        }

        List<Feature> features = new ArrayList<>();
        for (final String featureFile : config.getFeatureFiles()) {
            for (final String initFile : IOUtils.getFeatureFiles(config.getHomeDirectory(), featureFile)) {
                logger.debug("Reading feature file {}", initFile);
                final ArtifactHandler featureArtifact = artifactManager.getArtifactHandler(initFile);
                try (final Reader r = new InputStreamReader(featureArtifact.getLocalURL().openStream(), "UTF-8")) {
                    final Feature f = FeatureJSONReader.read(r, featureArtifact.getUrl());
                    loadedFeatures.put(f.getId(), f);
                    features.add(f);
                } catch (Exception ex) {
                    throw new IOException("Error reading feature: " + initFile, ex);
                }
            }
        }

        // TODO make feature id configurable
        final Feature app = FeatureBuilder.assemble(ArtifactId.fromMvnId("group:assembled:1.0.0"), builderContext, features.toArray(new Feature[0]));
        loadedFeatures.put(app.getId(), app);

        // TODO: this sucks
        for (Artifact bundle : app.getBundles()) {
            if ( bundle.getStartOrder() == 0) {
                final int so = bundle.getMetadata().get("start-level") != null ? Integer.parseInt(bundle.getMetadata().get("start-level")) : 1;
                bundle.setStartOrder(so);
            }
        }

        FeatureBuilder.resolveVariables(app, config.getVariables());

        return app;
    }

    /**
     * Prepare the launcher
     * - add all bundles to the bundle map of the installation object
     * - add all other artifacts to the install directory (only if startup mode is INSTALL)
     * - process configurations
     * @param ctx The launcher prepare context
     * @param config The launcher configuration
     * @param app The merged feature to launch
     * @param loadedFeatures The features previously loaded by the launcher, this includes features that
     * were passed in via file:// URLs from the commandline
     * @throws Exception when something goes wrong
     */
    public static void prepareLauncher(final LauncherPrepareContext ctx, final LauncherConfig config,
            final Feature app, Map<ArtifactId, Feature> loadedFeatures) throws Exception {
        for(final Map.Entry<Integer, List<Artifact>> entry : app.getBundles().getBundlesByStartOrder().entrySet()) {
            for(final Artifact a : entry.getValue()) {
                final URL artifactFile = ctx.getArtifactFile(a.getId());

                config.getInstallation().addBundle(entry.getKey(), artifactFile);
            }
        }

        for (final Configuration cfg : app.getConfigurations()) {
            if (Configuration.isFactoryConfiguration(cfg.getPid())) {
                config.getInstallation().addConfiguration(Configuration.getName(cfg.getPid()),
                        Configuration.getFactoryPid(cfg.getPid()), cfg.getConfigurationProperties());
            } else {
                config.getInstallation().addConfiguration(cfg.getPid(), null, cfg.getConfigurationProperties());
            }
        }

        for (final Map.Entry<String, String> prop : app.getFrameworkProperties().entrySet()) {
            if ( !config.getInstallation().getFrameworkProperties().containsKey(prop.getKey()) ) {
                config.getInstallation().getFrameworkProperties().put(prop.getKey(), prop.getValue());
            }
        }

        extensions: for(final Extension ext : app.getExtensions()) {
            Iterator<ExtensionHandler> i = ServiceLoader.load(ExtensionHandler.class,  FeatureProcessor.class.getClassLoader()).iterator();
            // Stream the iterator, sort them based on Priority in reversed order and then collection into a list
            List<ExtensionHandler> prioritizedExtensionHandlerList =
                StreamSupport
                    .stream(Spliterators.spliteratorUnknownSize(i, Spliterator.ORDERED), false)
                    .sorted(Comparator.comparingInt(ExtensionHandler::getPriority).reversed())
                    .collect(Collectors.toList());
            for (ExtensionHandler handler : prioritizedExtensionHandlerList)
            {
                if (handler.handle(new ExtensionContextImpl(ctx, config.getInstallation(), loadedFeatures), ext)) {
                    continue extensions;
                }
            }
            if ( ext.isRequired() ) {
                throw new Exception("Unknown required extension " + ext.getName());
            }
        }
    }
}
