/*
 * 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.testing.clients.osgi;

import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;


/** Utility that installs and starts additional bundles for testing */ 
public class BundlesInstaller {
    private final Logger log = LoggerFactory.getLogger(getClass());
    private final WebconsoleClient webconsoleClient;
    public static final String ACTIVE_STATE = "active";
    
    public BundlesInstaller(WebconsoleClient wcc) {
        webconsoleClient = wcc;
    }
   
    public boolean isInstalled(File bundleFile) throws Exception {
        final String bundleSymbolicName = getBundleSymbolicName(bundleFile);
        try{
            log.debug("Checking if installed: "+bundleSymbolicName);
            webconsoleClient.checkBundleInstalled(bundleSymbolicName, 1);
            // if this succeeds, then there's no need to install again
            log.debug("Already installed: "+bundleSymbolicName);
            return true;
        } catch(AssertionError e) {
            log.debug("Not yet installed: "+bundleSymbolicName);
            return false;
        }

    }
    
    /** Check if the installed version matches the one of the bundle (file) **/
    public boolean isInstalledWithSameVersion(File bundleFile) throws Exception {
        final String bundleSymbolicName = getBundleSymbolicName(bundleFile);
        final String versionOnServer = webconsoleClient.getBundleVersion(bundleSymbolicName);
        final String versionInBundle = getBundleVersion(bundleFile);
        if (versionOnServer.equals(versionInBundle)) {
            return true;
        } else {
            log.info("Bundle installed doesn't match: "+bundleSymbolicName+
                    ", versionOnServer="+versionOnServer+", versionInBundle="+versionInBundle);
            return false;
        }
    }
    
    /** Install a list of bundles supplied as Files */
    public void installBundles(List<File> toInstall, boolean startBundles) throws Exception {
        for(File f : toInstall) {
            final String bundleSymbolicName = getBundleSymbolicName(f);
            if (isInstalled(f)) {
                if (f.getName().contains("SNAPSHOT")) {
                    log.info("Reinstalling (due to SNAPSHOT version): {}", bundleSymbolicName);
                    webconsoleClient.uninstallBundle(bundleSymbolicName, f);
                } else if (!isInstalledWithSameVersion(f)) {
                    log.info("Reinstalling (due to version mismatch): {}", bundleSymbolicName);
                    webconsoleClient.uninstallBundle(bundleSymbolicName, f);
                } else {
                    log.info("Not reinstalling: {}", bundleSymbolicName);
                    continue;
                }
            }
            webconsoleClient.installBundle(f, startBundles);
            log.info("Installed: {}", bundleSymbolicName);
        }
        
        // ensure that bundles are re-wired esp. if an existing bundle was updated
        webconsoleClient.refreshPackages();

        log.info("{} additional bundles installed", toInstall.size());
    }
    
    /** Uninstall a list of bundles supplied as Files */
    public void uninstallBundles(List<File> toUninstall) throws Exception {
        for(File f : toUninstall) {
            final String bundleSymbolicName = getBundleSymbolicName(f);
            if (isInstalled(f)) {
                log.info("Uninstalling bundle: {}", bundleSymbolicName);
                webconsoleClient.uninstallBundle(bundleSymbolicName, f);
            } else {
                log.info("Could not uninstall: {} as it never was installed", bundleSymbolicName);
            }
        }
        
        // ensure that bundles are re-wired esp. if an existing bundle was updated
        webconsoleClient.refreshPackages();

        log.info("{} additional bundles uninstalled", toUninstall.size());
    }
    
    /** Wait for all bundles specified in symbolicNames list to be installed in the
     *  remote web console.
     */
    public void waitForBundlesInstalled(List<String> symbolicNames, int timeoutSeconds) throws Exception {
        log.info("Checking that bundles are installed (timeout {} seconds): {}", timeoutSeconds, symbolicNames);
        for(String symbolicName : symbolicNames) {
            webconsoleClient.checkBundleInstalled(symbolicName, timeoutSeconds);
        }
    }
    
    public void startAllBundles(List<String> symbolicNames, int timeoutSeconds) throws Exception {
        log.info("Starting bundles (timeout {} seconds): {}", timeoutSeconds, symbolicNames);
        
        final long timeout = System.currentTimeMillis() + timeoutSeconds * 1000L;
        final List<String> toStart = new LinkedList<String>();
        while(System.currentTimeMillis() < timeout) {
            toStart.clear();
            for(String name : symbolicNames) {
                final String state = webconsoleClient.getBundleState(name);
                if(!state.equalsIgnoreCase(ACTIVE_STATE)) {
                    toStart.add(name);
                    break;
                }
            }
            
            if(toStart.isEmpty()) {
                log.info("Ok - all bundles are in the {} state", ACTIVE_STATE);
                break;
            }
            
            for(String name : toStart) {
                webconsoleClient.startBundle(name);
            }
            
            Thread.sleep(500L);
        }
        
        if(!toStart.isEmpty()) {
            throw new Exception("Some bundles did not start: " + toStart);
        }
    }
    
    public String getBundleSymbolicName(File bundleFile) throws IOException {
        String name = null;
        final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
        try {
            final Manifest m = jis.getManifest();
            if (m == null) {
                throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
            }
            name = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
        } finally {
            jis.close();
        }
        return name;
    }
    
    public String getBundleVersion(File bundleFile) throws IOException {
        String version = null;
        final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
        try {
            final Manifest m = jis.getManifest();
            if(m == null) {
                throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
            }
            version = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
        } finally {
            jis.close();
        }
        return version;
    }
}