/*
 * 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.profile.assembly;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.jar.Attributes;
import java.util.jar.JarFile;

import org.apache.felix.utils.properties.Properties;
import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.DeploymentEvent;
import org.apache.karaf.features.FeatureEvent;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.internal.download.DownloadManager;
import org.apache.karaf.features.internal.download.Downloader;
import org.apache.karaf.features.internal.model.Config;
import org.apache.karaf.features.internal.model.ConfigFile;
import org.apache.karaf.features.internal.model.Feature;
import org.apache.karaf.features.internal.model.Features;
import org.apache.karaf.features.internal.model.Library;
import org.apache.karaf.features.internal.service.Deployer;
import org.apache.karaf.features.internal.service.FeaturesProcessor;
import org.apache.karaf.features.internal.service.State;
import org.apache.karaf.features.internal.service.StaticInstallSupport;
import org.apache.karaf.features.internal.util.MapUtils;
import org.apache.karaf.util.maven.Parser;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.wiring.BundleRevision;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Callback through which {@link Deployer} will interact with the distribution that's being assembled.
 */
public class AssemblyDeployCallback extends StaticInstallSupport implements Deployer.DeployCallback {

    private static final Logger LOGGER = LoggerFactory.getLogger(Builder.class);

    private final DownloadManager manager;
    private final Builder builder;
    private final Path homeDirectory;
    private final int defaultStartLevel;
    private final Path etcDirectory;
    private final Path systemDirectory;
    private final Deployer.DeploymentState dstate;
    private final AtomicLong nextBundleId = new AtomicLong(0);
    private final FeaturesProcessor processor;

    private final Map<String, Bundle> bundles = new HashMap<>();

    /**
     * Create a {@link Deployer.DeployCallback} performing actions on runtime with single system bundle installed
     * and with access to all non-blacklisted features.
     * @param manager
     * @param builder
     * @param systemBundle
     * @param repositories
     * @param processor
     */
    public AssemblyDeployCallback(DownloadManager manager, Builder builder, BundleRevision systemBundle, Collection<Features> repositories,
                                  FeaturesProcessor processor) {
        this.manager = manager;
        this.builder = builder;
        this.homeDirectory = builder.homeDirectory;
        this.etcDirectory = homeDirectory.resolve("etc");
        this.systemDirectory = homeDirectory.resolve("system");
        this.defaultStartLevel = builder.defaultStartLevel;
        this.processor = processor;

        dstate = new Deployer.DeploymentState();
        dstate.bundles = new HashMap<>();
        dstate.bundlesPerRegion = new HashMap<>();
        dstate.filtersPerRegion = new HashMap<>();
        dstate.state = new State();

        MapUtils.addToMapSet(dstate.bundlesPerRegion, FeaturesService.ROOT_REGION, 0l);
        dstate.bundles.put(0l, systemBundle.getBundle());

        Collection<org.apache.karaf.features.Feature> features = new LinkedList<>();
        for (Features repo : repositories) {
            if (repo.isBlacklisted()) {
                continue;
            }
            for (Feature f : repo.getFeature()) {
                if (!f.isBlacklisted()) {
                    features.add(f);
                }
            }
        }
        dstate.partitionFeatures(features);
    }

    /**
     * Get startup bundles with related start-level
     * @return
     */
    public Map<String, Integer> getStartupBundles() {
        Map<String, Integer> startup = new HashMap<>();
        for (Map.Entry<String, Bundle> bundle : bundles.entrySet()) {
            int level = bundle.getValue().adapt(BundleStartLevel.class).getStartLevel();
            if (level <= 0) {
                level = defaultStartLevel;
            }
            startup.put(bundle.getKey(), level);
        }
        return startup;
    }

    public Deployer.DeploymentState getDeploymentState() {
        return dstate;
    }

    @Override
    public void saveState(State state) {
        dstate.state.replace(state);
    }

    @Override
    public void persistResolveRequest(Deployer.DeploymentRequest request) {
    }

    @Override
    public void installConfigs(org.apache.karaf.features.Feature feature) throws IOException {
        assertNotBlacklisted(feature);
        // Install
        Downloader downloader = manager.createDownloader();
        for (Config config : ((Feature) feature).getConfig()) {
            Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
            if (Files.exists(configFile) && !config.isAppend()) {
                LOGGER.info("      not changing existing config file: {}", homeDirectory.relativize(configFile));
                continue;
            }
            if (config.isExternal()) {
                downloader.download(config.getValue().trim(), provider -> {
                    Path input = provider.getFile().toPath();
                    byte[] data = Files.readAllBytes(input);
                    if (config.isAppend()) {
                        LOGGER.info("      appending to config file: {}", homeDirectory.relativize(configFile));
                        Files.write(configFile, data, StandardOpenOption.APPEND);
                    } else {
                        LOGGER.info("      adding config file: {}", homeDirectory.relativize(configFile));
                        Files.write(configFile, data);
                    }
                });
            } else {
                byte[] data = config.getValue().getBytes();
                if (config.isAppend()) {
                    LOGGER.info("      appending to config file: {}", homeDirectory.relativize(configFile));
                    Files.write(configFile, data, StandardOpenOption.APPEND);
                } else {
                    LOGGER.info("      adding config file: {}", homeDirectory.relativize(configFile));
                    Files.write(configFile, data);
                }
            }
        }
        for (final ConfigFile configFile : ((Feature) feature).getConfigfile()) {
            String path = configFile.getFinalname();
            if (path.startsWith("/")) {
                path = path.substring(1);
            }
            path = substFinalName(path);
            final Path output = homeDirectory.resolve(path);
            final String finalPath = path;
            if (configFile.isOverride() || !Files.exists(output)) {
                downloader.download(configFile.getLocation(), provider -> {
                    Path input = provider.getFile().toPath();
                    if (configFile.isOverride()) {
                        LOGGER.info("      overwriting config file: {}", finalPath);
                    } else {
                        LOGGER.info("      adding config file: {}", finalPath);
                    }
                    Files.copy(input, output, StandardCopyOption.REPLACE_EXISTING);
                });
            }
        }
    }

    @Override
    public void deleteConfigs(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
        // nothing to do
    }

    @Override
    public void installLibraries(org.apache.karaf.features.Feature feature) throws IOException {
        assertNotBlacklisted(feature);
        Downloader downloader = manager.createDownloader();
        List<String> libraries = new ArrayList<>();
        for (Library library : ((Feature) feature).getLibraries()) {
            String lib = library.getLocation() +
                    ";type:=" + library.getType() +
                    ";export:=" + library.isExport() +
                    ";delegate:=" + library.isDelegate();
            libraries.add(lib);
        }
        if (!libraries.isEmpty()) {
            Path configPropertiesPath = etcDirectory.resolve("config.properties");
            Properties configProperties = new Properties(configPropertiesPath.toFile());
            builder.downloadLibraries(downloader, configProperties, libraries, "   ");
        }
        try {
            downloader.await();
        } catch (Exception e) {
            throw new IOException("Error downloading configuration files", e);
        }
    }
    
    private void assertNotBlacklisted(org.apache.karaf.features.Feature feature) {
        if (feature.isBlacklisted()) {
            if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
                throw new RuntimeException("Feature " + feature.getId() + " is blacklisted");
            }
        }
    }

    @Override
    public void callListeners(DeploymentEvent deployEvent) {
    }

    @Override
    public void callListeners(FeatureEvent featureEvent) {
    }

    @Override
    public Bundle installBundle(String region, String uri, InputStream is) throws BundleException {
        // Check blacklist
        if (processor.isBundleBlacklisted(uri)) {
            if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
                throw new RuntimeException("Bundle " + uri + " is blacklisted");
            }
        }

        // Install
        LOGGER.info("      adding maven artifact: " + uri);
        try {
            String regUri;
            String path;
            if (uri.startsWith("mvn:")) {
                regUri = uri;
                path = Parser.pathFromMaven(uri);
            } else {
                uri = uri.replaceAll("[^0-9a-zA-Z.\\-_]+", "_");
                if (uri.length() > 256) {
                    //to avoid the File name too long exception
                    uri = uri.substring(0, 255);
                }
                path = "generated/" + uri;
                regUri = "file:" + path;
            }
            final Path bundleSystemFile = systemDirectory.resolve(path);
            Files.createDirectories(bundleSystemFile.getParent());
            Files.copy(is, bundleSystemFile, StandardCopyOption.REPLACE_EXISTING);

            Hashtable<String, String> headers = new Hashtable<>();
            try (JarFile jar = new JarFile(bundleSystemFile.toFile())) {
                Attributes attributes = jar.getManifest().getMainAttributes();
                for (Map.Entry<Object, Object> attr : attributes.entrySet()) {
                    headers.put(attr.getKey().toString(), attr.getValue().toString());
                }
            }
            BundleRevision revision = new FakeBundleRevision(headers, uri, nextBundleId.incrementAndGet());
            Bundle bundle = revision.getBundle();
            MapUtils.addToMapSet(dstate.bundlesPerRegion, region, bundle.getBundleId());
            dstate.bundles.put(bundle.getBundleId(), bundle);

            bundles.put(regUri, bundle);
            return bundle;
        } catch (IOException e) {
            throw new BundleException("Unable to install bundle", e);
        }
    }

    @Override
    public void setBundleStartLevel(Bundle bundle, int startLevel) {
        bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
    }

    @Override
    public void bundleBlacklisted(BundleInfo bundleInfo) {
        LOGGER.info("      skipping blacklisted bundle: {}", bundleInfo.getLocation());
    }

    private String substFinalName(String finalname) {
        final String markerVarBeg = "${";
        final String markerVarEnd = "}";

        boolean startsWithVariable = finalname.startsWith(markerVarBeg) && finalname.contains(markerVarEnd);
        if (startsWithVariable) {
            String marker = finalname.substring(markerVarBeg.length(), finalname.indexOf(markerVarEnd));
            switch (marker) {
            case "karaf.base":
                return this.homeDirectory + finalname.substring(finalname.indexOf(markerVarEnd)+markerVarEnd.length());
            case "karaf.etc":
                return this.etcDirectory + finalname.substring(finalname.indexOf(markerVarEnd)+markerVarEnd.length());
            default:
                break;
            }
        }
        return finalname;
    }

}
