/*
 * Licensed 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.cellar.features.management.internal;

// import org.apache.karaf.cellar.bundle.BundleState;

import org.apache.karaf.cellar.core.*;
import org.apache.karaf.cellar.core.control.SwitchStatus;
import org.apache.karaf.cellar.core.event.EventProducer;
import org.apache.karaf.cellar.core.event.EventType;
import org.apache.karaf.cellar.features.ClusterFeaturesEvent;
import org.apache.karaf.cellar.features.Constants;
import org.apache.karaf.cellar.features.FeatureState;
import org.apache.karaf.cellar.features.ClusterRepositoryEvent;
import org.apache.karaf.cellar.features.management.CellarFeaturesMBean;
import org.apache.karaf.features.*;
// import org.osgi.framework.BundleEvent;
import org.apache.karaf.features.internal.model.Features;
import org.apache.karaf.features.internal.model.JaxbUtil;
import org.osgi.service.cm.ConfigurationAdmin;

import javax.management.NotCompliantMBeanException;
import javax.management.StandardMBean;
import javax.management.openmbean.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Implementation of the Cellar Features MBean.
 */
public class CellarFeaturesMBeanImpl extends StandardMBean implements CellarFeaturesMBean {

    private ClusterManager clusterManager;
    private GroupManager groupManager;
    private EventProducer eventProducer;
    private FeaturesService featuresService;
    private ConfigurationAdmin configurationAdmin;

    public CellarFeaturesMBeanImpl() throws NotCompliantMBeanException {
        super(CellarFeaturesMBean.class);
    }

    public ClusterManager getClusterManager() {
        return this.clusterManager;
    }

    public void setClusterManager(ClusterManager clusterManager) {
        this.clusterManager = clusterManager;
    }

    public GroupManager getGroupManager() {
        return this.groupManager;
    }

    public void setGroupManager(GroupManager groupManager) {
        this.groupManager = groupManager;
    }

    public EventProducer getEventProducer() {
        return eventProducer;
    }

    public void setEventProducer(EventProducer eventProducer) {
        this.eventProducer = eventProducer;
    }

    public FeaturesService getFeaturesService() {
        return featuresService;
    }

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

    public ConfigurationAdmin getConfigurationAdmin() {
        return configurationAdmin;
    }

    public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
        this.configurationAdmin = configurationAdmin;
    }

    @Override
    public void installFeature(String groupName, String name, String version, boolean noClean, boolean noRefresh) throws Exception {
        this.installFeature(groupName, name, version, noClean, noRefresh, false);
    }

    @Override
    public void installFeature(String groupName, String name, String version, boolean noClean, boolean noRefresh, boolean noStart) throws Exception {
        // check if the group exists
        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        // check if the producer is ON
        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
            throw new IllegalStateException("Cluster event producer is OFF");
        }

        // check if the feature is allowed outbound
        CellarSupport support = new CellarSupport();
        support.setClusterManager(this.clusterManager);
        support.setGroupManager(this.groupManager);
        support.setConfigurationAdmin(this.configurationAdmin);
        if (!support.isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND)) {
            throw new IllegalArgumentException("Feature " + name + " is blocked outbound for cluster group " + groupName);
        }

        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        try {

            // get the features in the cluster group
            Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);

            // check if the feature exist
            FeatureState feature = null;
            String key = null;
            for (String k : clusterFeatures.keySet()) {
                FeatureState state = clusterFeatures.get(k);
                key = k;
                if (version == null) {
                    if (state.getName().equals(name)) {
                        feature = state;
                        break;
                    }
                } else {
                    if (state.getName().equals(name) && state.getVersion().equals(version)) {
                        feature = state;
                        break;
                    }
                }
            }

            if (feature == null) {
                if (version == null)
                    throw new IllegalArgumentException("Feature " + name + " doesn't exist in cluster group " + groupName);
                else
                    throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName);
            }

            // update the cluster group
            feature.setInstalled(true);
            clusterFeatures.put(key, feature);
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }

        // broadcast the cluster event
        ClusterFeaturesEvent event = new ClusterFeaturesEvent(name, version, noClean, noRefresh, noStart, FeatureEvent.EventType.FeatureInstalled);
        event.setSourceGroup(group);
        eventProducer.produce(event);
    }

    @Override
    public void installFeature(String groupName, String name, String version) throws Exception {
        this.installFeature(groupName, name, version, false, false);
    }

    @Override
    public void installFeature(String groupName, String name) throws Exception {
        this.installFeature(groupName, name, null);
    }

    @Override
    public void installFeature(String groupName, String name, boolean noClean, boolean noRefresh) throws Exception {
        this.installFeature(groupName, name, null, noClean, noRefresh, false);
    }

    @Override
    public void installFeature(String groupName, String name, boolean noClean, boolean noRefresh, boolean noStart) throws Exception {
        this.installFeature(groupName, name, null, noClean, noRefresh, noStart);
    }

    @Override
    public void uninstallFeature(String groupName, String name, String version) throws Exception {
        this.uninstallFeature(groupName, name, version, false);
    }

    @Override
    public void uninstallFeature(String groupName, String name, String version, boolean noRefresh) throws Exception {
        // check if the group exists
        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        // check if the producer is ON
        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
            throw new IllegalStateException("Cluster event producer is OFF");
        }

        // check if the feature is allowed outbound
        CellarSupport support = new CellarSupport();
        support.setClusterManager(this.clusterManager);
        support.setGroupManager(this.groupManager);
        support.setConfigurationAdmin(this.configurationAdmin);
        if (!support.isAllowed(group, Constants.CATEGORY, name, EventType.OUTBOUND)) {
            throw new IllegalArgumentException("Feature " + name + " is blocked outbound for cluster group " + groupName);
        }

        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        try {

            // get the features in the cluster group
            Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);

            // check if the feature exist
            FeatureState feature = null;
            String key = null;
            for (String k : clusterFeatures.keySet()) {
                FeatureState state = clusterFeatures.get(k);
                key = k;
                if (version == null) {
                    if (state.getName().equals(name)) {
                        feature = state;
                        break;
                    }
                } else {
                    if (state.getName().equals(name) && state.getVersion().equals(version)) {
                        feature = state;
                        break;
                    }
                }
            }

            if (feature == null) {
                if (version == null)
                    throw new IllegalArgumentException("Feature " + name + " doesn't exist in cluster group " + groupName);
                else
                    throw new IllegalArgumentException("Feature " + name + "/" + version + " doesn't exist in cluster group " + groupName);
            }

            // update the cluster group
            feature.setInstalled(false);
            clusterFeatures.put(key, feature);
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }

        // broadcast the cluster event
        ClusterFeaturesEvent event = new ClusterFeaturesEvent(name, version, false, noRefresh, false, FeatureEvent.EventType.FeatureUninstalled);
        event.setSourceGroup(group);
        eventProducer.produce(event);
    }

    @Override
    public void uninstallFeature(String groupName, String name) throws Exception {
        this.uninstallFeature(groupName, name, null, false);
    }

    @Override
    public void uninstallFeature(String groupName, String name, boolean noRefresh) throws Exception {
        this.uninstallFeature(groupName, name, null, noRefresh);
    }

    @Override
    public TabularData getFeatures(String groupName) throws Exception {

        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        CellarSupport support = new CellarSupport();
        support.setClusterManager(clusterManager);
        support.setGroupManager(groupManager);
        support.setConfigurationAdmin(configurationAdmin);

        CompositeType featuresType = new CompositeType("Feature", "Karaf Cellar feature",
                new String[]{"name", "version", "installed", "located", "blocked"},
                new String[]{"Name of the feature", "Version of the feature", "Whether the feature is installed or not",
                        "Location of the feature (on the cluster or the local node)",
                        "Feature block policy"},
                new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.BOOLEAN});

        TabularType tabularType = new TabularType("Features", "Table of all Karaf Cellar features",
                featuresType, new String[]{"name", "version"});
        TabularData table = new TabularDataSupport(tabularType);

        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        try {
            Map<String, ExtendedFeatureState> features = gatherFeatures(groupName);
            if (features != null && !features.isEmpty()) {
                for (ExtendedFeatureState feature : features.values()) {

                    String located = "";
                    boolean cluster = feature.isCluster();
                    boolean local = feature.isLocal();
                    if (cluster && local)
                        located = "cluster/local";
                    if (cluster && !local)
                        located = "cluster";
                    if (local && !cluster)
                        located = "local";

                    String blocked = "";
                    boolean inbound = support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.INBOUND);
                    boolean outbound = support.isAllowed(group, Constants.CATEGORY, feature.getName(), EventType.OUTBOUND);
                    if (!inbound && !outbound)
                        blocked = "in/out";
                    if (!inbound && outbound)
                        blocked = "in";
                    if (!outbound && inbound)
                        blocked = "out";

                    CompositeData data = new CompositeDataSupport(featuresType,
                            new String[]{"name", "version", "installed", "located", "blocked"},
                            new Object[]{feature.getName(), feature.getVersion(), feature.getInstalled(), located, blocked});
                    table.put(data);
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }

        return table;
    }

    private Map<String, ExtendedFeatureState> gatherFeatures(String groupName) throws Exception {
        Map<String, ExtendedFeatureState> features = new HashMap<String, ExtendedFeatureState>();

        // get cluster features
        Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);
        for (String key : clusterFeatures.keySet()) {
            FeatureState state = clusterFeatures.get(key);
            ExtendedFeatureState extendedState = new ExtendedFeatureState();
            extendedState.setName(state.getName());
            extendedState.setInstalled(state.getInstalled());
            extendedState.setVersion(state.getVersion());
            extendedState.setCluster(true);
            extendedState.setLocal(true);
            features.put(key, extendedState);
        }

        // get local features
        for (Feature feature : featuresService.listFeatures()) {
            String key = feature.getName() + "/" + feature.getVersion();
            if (features.containsKey(key)) {
                ExtendedFeatureState extendedState = features.get(key);
                if (featuresService.isInstalled(feature))
                    extendedState.setInstalled(true);
                extendedState.setLocal(true);
            } else {
                ExtendedFeatureState extendedState = new ExtendedFeatureState();
                extendedState.setCluster(false);
                extendedState.setLocal(true);
                extendedState.setName(feature.getName());
                extendedState.setVersion(feature.getVersion());
                if (featuresService.isInstalled(feature))
                    extendedState.setInstalled(true);
                else extendedState.setInstalled(false);
                features.put(key, extendedState);
            }
        }

        return features;
    }

    @Override
    public List<String> getRepositories(String groupName) throws Exception {
        // check if the group exists
        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        // get the features repositories in the cluster group
        Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);

        List<String> result = new ArrayList<String>();
        for (String clusterRepository : clusterRepositories.keySet()) {
            result.add(clusterRepository);
        }

        return result;
    }

    @Override
    public void addRepository(String groupName, String nameOrUrl) throws Exception {
        this.addRepository(groupName, nameOrUrl, null, false);
    }

    @Override
    public void addRepository(String groupName, String nameOrUrl, String version) throws Exception {
        this.addRepository(groupName, nameOrUrl, version, false);
    }

    @Override
    public void addRepository(String groupName, String nameOrUrl, String version, boolean install) throws Exception {
        // check if the group exists
        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        // check if the event producer is ON
        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
            throw new IllegalStateException("Cluster event producer is OFF");
        }

        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
        try {
            // get the features repositories in the cluster group
            Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
            // get the features in the cluster group
            Map<String, FeatureState> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);

            URI uri = featuresService.getRepositoryUriFor(nameOrUrl, version);
            if (uri == null) {
                uri = new URI(nameOrUrl);
            }

            // check if the URL is already registered
            String name = null;
            for (String repository : clusterRepositories.keySet()) {
                if (repository.equals(uri)) {
                    name = clusterRepositories.get(repository);
                    break;
                }
            }
            if (name == null) {
                // parsing the features repository to get content
                Features repository = JaxbUtil.unmarshal(uri.toASCIIString(), true);

                // update the cluster group
                clusterRepositories.put(uri.toString(), name);

                // update the features in the cluster group
                for (Feature feature : repository.getFeature()) {
                    FeatureState state = new FeatureState();
                    state.setName(feature.getName());
                    state.setVersion(feature.getVersion());
                    state.setInstalled(featuresService.isInstalled(feature));
                    clusterFeatures.put(feature.getName() + "/" + feature.getVersion(), state);
                }

                // broadcast the cluster event
                ClusterRepositoryEvent event = new ClusterRepositoryEvent(uri.toString(), RepositoryEvent.EventType.RepositoryAdded);
                event.setInstall(install);
                event.setSourceGroup(group);
                eventProducer.produce(event);
            } else {
                throw new IllegalArgumentException("Features repository URL " + uri + " already registered");
            }
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }
    }

    @Override
    public void removeRepository(String groupName, String repository) throws Exception {
        this.removeRepository(groupName, repository, false);
    }

    @Override
    public void removeRepository(String groupName, String repo, boolean uninstall) throws Exception {
        // check if the group exists
        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        // check if the event producer is ON
        if (eventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) {
            throw new IllegalStateException("Cluster event producer is OFF");
        }

        // get the features repositories in the cluster group
        Map<String, String> clusterRepositories = clusterManager.getMap(Constants.REPOSITORIES_MAP + Configurations.SEPARATOR + groupName);
        // get the features in the cluster group
        Map<FeatureState, Boolean> clusterFeatures = clusterManager.getMap(Constants.FEATURES_MAP + Configurations.SEPARATOR + groupName);

        ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());

            List<String> urls = new ArrayList<String>();
            Pattern pattern = Pattern.compile(repo);
            for (String repositoryUrl : clusterRepositories.keySet()) {
                String repositoryName = clusterRepositories.get(repositoryUrl);
                if (repositoryName != null && !repositoryName.isEmpty()) {
                    // repository has name, try regex on the name
                    Matcher nameMatcher = pattern.matcher(repositoryName);
                    if (nameMatcher.matches()) {
                        urls.add(repositoryUrl);
                    } else {
                        // the name regex doesn't match, fallback to repository URI regex
                        Matcher uriMatcher = pattern.matcher(repositoryUrl);
                        if (uriMatcher.matches()) {
                            urls.add(repositoryUrl);
                        }
                    }
                } else {
                    // the repository name is not defined, use repository URI regex
                    Matcher uriMatcher = pattern.matcher(repositoryUrl);
                    if (uriMatcher.matches()) {
                        urls.add(repositoryUrl);
                    }
                }
            }

            for (String url : urls) {
                // looking for the URL in the list
                boolean found = false;
                for (String repository : clusterRepositories.keySet()) {
                    if (repository.equals(repository)) {
                        found = true;
                        break;
                    }
                }
                if (found) {
                    Features repositoryModel = JaxbUtil.unmarshal(url, true);

                    // update the features repositories in the cluster group
                    clusterRepositories.remove(url);

                    // update the features in the cluster group
                    for (Feature feature : repositoryModel.getFeature()) {
                        clusterFeatures.remove(feature.getName() + "/" + feature.getVersion());
                    }

                    // broadcast a cluster event
                    ClusterRepositoryEvent event = new ClusterRepositoryEvent(url, RepositoryEvent.EventType.RepositoryRemoved);
                    event.setUninstall(uninstall);
                    event.setSourceGroup(group);
                    eventProducer.produce(event);
                } else {
                    throw new IllegalArgumentException("Features repository URL " + url + " not found in cluster group " + groupName);
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(originalClassLoader);
        }
    }

    @Override
    public void block(String groupName, String featurePattern, boolean whitelist, boolean blacklist, boolean in, boolean out) throws Exception {

        Group group = groupManager.findGroupByName(groupName);
        if (group == null) {
            throw new IllegalArgumentException("Cluster group " + groupName + " doesn't exist");
        }

        CellarSupport support = new CellarSupport();
        support.setClusterManager(clusterManager);
        support.setGroupManager(groupManager);
        support.setConfigurationAdmin(configurationAdmin);

        if (in) {
            if (whitelist)
                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
            if (blacklist)
                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.INBOUND, featurePattern);
        }
        if (out) {
            if (whitelist)
                support.switchListEntry(Configurations.WHITELIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
            if (blacklist)
                support.switchListEntry(Configurations.BLACKLIST, groupName, Constants.CATEGORY, EventType.OUTBOUND, featurePattern);
        }

    }

    class ExtendedFeatureState extends FeatureState {

        private boolean cluster;
        private boolean local;

        public boolean isCluster() {
            return cluster;
        }

        public void setCluster(boolean cluster) {
            this.cluster = cluster;
        }

        public boolean isLocal() {
            return local;
        }

        public void setLocal(boolean local) {
            this.local = local;
        }
    }

}
