/*
 * 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.deployer.features;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.karaf.features.internal.FeatureImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import org.apache.felix.fileinstall.ArtifactUrlTransformer;
import org.apache.karaf.features.Feature;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.Repository;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * A deployment listener able to hot deploy a feature descriptor
 */
public class FeatureDeploymentListener implements ArtifactUrlTransformer, BundleListener {

    public static final String FEATURE_PATH = "org.apache.karaf.shell.features";

    private final Logger logger = LoggerFactory.getLogger(FeatureDeploymentListener.class);

    private DocumentBuilderFactory dbf;
    private FeaturesService featuresService;
    private BundleContext bundleContext;

    public void setFeaturesService(FeaturesService featuresService) {
        this.featuresService = featuresService;
    }

    public FeaturesService getFeaturesService() {
        return featuresService;
    }

    public BundleContext getBundleContext() {
        return bundleContext;
    }

    public void setBundleContext(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }

    public void init() throws Exception {
        bundleContext.addBundleListener(this);
        for (Bundle bundle : bundleContext.getBundles()) {
            if (bundle.getState() == Bundle.RESOLVED || bundle.getState() == Bundle.STARTING
                    || bundle.getState() == Bundle.ACTIVE)
            bundleChanged(new BundleEvent(BundleEvent.RESOLVED, bundle));
        }
    }

    public void destroy() throws Exception {
        bundleContext.removeBundleListener(this);
    }

    public boolean canHandle(File artifact) {
        try {
            if (artifact.isFile() && artifact.getName().endsWith(".xml")) {
                Document doc = parse(artifact);
                String name = doc.getDocumentElement().getLocalName();
                String uri  = doc.getDocumentElement().getNamespaceURI();
                if ("features".equals(name) && (uri == null || "".equals(uri)  || "http://karaf.apache.org/xmlns/features/v1.0.0".equalsIgnoreCase(uri))) {
                    return true;
                }
            }
        } catch (Exception e) {
            logger.error("Unable to parse deployed file " + artifact.getAbsolutePath(), e);
        }
        return false;
    }

    public URL transform(URL artifact) {
        // We can't really install the feature right now and just return nothing.
        // We would not be aware of the fact that the bundle has been uninstalled
        // and therefore require the feature to be uninstalled.
        // So instead, create a fake bundle with the file inside, which will be listened by
        // this deployer: installation / uninstallation of the feature will be done
        // while the bundle is installed / uninstalled.
        try {
            return new URL("feature", null, artifact.toString());
        } catch (Exception e) {
            logger.error("Unable to build feature bundle", e);
            return null;
        }
    }

    public void bundleChanged(BundleEvent bundleEvent) {
            Bundle bundle = bundleEvent.getBundle();
            if (bundleEvent.getType() == BundleEvent.RESOLVED) {
                try {
                    List<URL> urls = new ArrayList<URL>();
                    Enumeration featuresUrlEnumeration = bundle.findEntries("/META-INF/" + FEATURE_PATH + "/", "*.xml", false);
                    while (featuresUrlEnumeration != null && featuresUrlEnumeration.hasMoreElements()) {
                        URL url = (URL) featuresUrlEnumeration.nextElement();
                        try {
                            featuresService.addRepository(url.toURI());
                            for (Repository repo : featuresService.listRepositories()) {
                                if (repo.getURI().equals(url.toURI())) {
                                    Set<Feature> features = new HashSet<Feature>(Arrays.asList(repo.getFeatures()));
                                    Set<Feature> autoInstallFeatures = new HashSet<Feature>();
                                    for(Feature feature:features) {
                                        if(feature.getInstall().equals(Feature.DEFAULT_INSTALL_MODE)){
                                            autoInstallFeatures.add(feature);
                                        }
                                    }
                                    featuresService.installFeatures(autoInstallFeatures, EnumSet.noneOf(FeaturesService.Option.class));
                                }
                            }
                            urls.add(url);
                        } catch (Exception e) {
                            logger.error("Unable to install features", e);
                        }
                    }
                    synchronized (this) {
                        File file = bundleContext.getDataFile("FeatureDeploymentListener.cfg");
                        if (file != null) {
                            Properties props = new Properties();
                            if (file.exists()) {
                                InputStream input = new FileInputStream(file);
                                try {
                                    props.load(input);
                                } finally {
                                    input.close();
                                }
                            }
                            String prefix = bundle.getSymbolicName() + "-" + bundle.getVersion();
                            props.put(prefix + ".count", Integer.toString(urls.size()));
                            for (int i = 0; i < urls.size(); i++) {
                                props.put(prefix + ".url." + i, urls.get(i).toExternalForm());
                            }
                            OutputStream output = new FileOutputStream(file);
                            try {
                                props.store(output, null);
                            } finally {
                                output.close();
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("Unable to install deployed features for bundle: " + bundle.getSymbolicName() + " - " + bundle.getVersion(), e);
                }
            } else if (bundleEvent.getType() == BundleEvent.UNINSTALLED) {
                try {
                    synchronized (this) {
                        File file = bundleContext.getDataFile("FeatureDeploymentListener.cfg");
                        if (file != null) {
                            Properties props = new Properties();
                            if (file.exists()) {
                                InputStream input = new FileInputStream(file);
                                try {
                                    props.load(input);
                                } finally {
                                    input.close();
                                }
                            }
                            String prefix = bundle.getSymbolicName() + "-" + bundle.getVersion();
                            String countStr = (String) props.get(prefix + ".count");
                            if (countStr != null) {
                                int count = Integer.parseInt(countStr);
                                for (int i = 0; i < count; i++) {
                                    URL url = new URL((String) props.get(prefix + ".url." + i));
                                    for (Repository repo : featuresService.listRepositories()) {
                                        try {
                                            if (repo.getURI().equals(url.toURI())) {
                                                for (Feature f : repo.getFeatures()) {
                                                    try {
                                                        featuresService.uninstallFeature(f.getName(), f.getVersion());
                                                    } catch (Exception e) {
                                                        logger.error("Unable to uninstall feature: " + f.getName(), e);
                                                    }
                                                }
                                            }
                                        } catch (Exception e) {
                                            logger.error("Unable to uninstall features: " + url, e);
                                        }
                                    }
                                    try {
                                        featuresService.removeRepository(url.toURI());
                                    } catch (URISyntaxException e) {
                                        logger.error("Unable to remove repository: " + url, e);
                                    }
                                }
                            }
                            for (Iterator<Object> it = props.keySet().iterator(); it.hasNext();) {
                                if (it.next().toString().startsWith(prefix + ".")) {
                                    it.remove();
                                }
                            }
                            OutputStream output = new FileOutputStream(file);
                            try {
                                props.store(output, null);
                            } finally {
                                output.close();
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("Unable to uninstall deployed features for bundle: " + bundle.getSymbolicName() + " - " + bundle.getVersion(), e);
                }
            }
    }

    protected Document parse(File artifact) throws Exception {
        if (dbf == null) {
            dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
        }
        DocumentBuilder db = dbf.newDocumentBuilder();
        db.setErrorHandler(new ErrorHandler() {
            public void warning(SAXParseException exception) throws SAXException {
            }
            public void error(SAXParseException exception) throws SAXException {
            }
            public void fatalError(SAXParseException exception) throws SAXException {
                throw exception;
            }
        });
        return db.parse(artifact);
    }

}
