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

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import org.apache.felix.configurator.impl.json.BinUtil;
import org.apache.felix.configurator.impl.json.JSONUtil;
import org.apache.felix.configurator.impl.json.TypeConverter;
import org.apache.felix.configurator.impl.logger.SystemLogger;
import org.apache.felix.configurator.impl.model.BundleState;
import org.apache.felix.configurator.impl.model.Config;
import org.apache.felix.configurator.impl.model.ConfigList;
import org.apache.felix.configurator.impl.model.ConfigPolicy;
import org.apache.felix.configurator.impl.model.ConfigState;
import org.apache.felix.configurator.impl.model.ConfigurationFile;
import org.apache.felix.configurator.impl.model.State;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.configurator.ConfiguratorConstants;
import org.osgi.util.tracker.BundleTrackerCustomizer;

/**
 * The main class of the configurator.
 *
 */
public class Configurator {

    private final BundleContext bundleContext;

    private final State state;

    private final org.osgi.util.tracker.BundleTracker<Bundle> tracker;

    private volatile boolean active = true;

    private volatile Object coordinator;

    private final WorkerQueue queue;

    private final List<ServiceReference<ConfigurationAdmin>> configAdminReferences;

    /**
     * Create a new configurator and start it
     *
     * @param bc The bundle context
     * @param configAdminReferences Dynamic list of references to the configuration admin service visible to the configurator
     */
    public Configurator(final BundleContext bc, final List<ServiceReference<ConfigurationAdmin>> configAdminReferences) {
        this.queue = new WorkerQueue();
        this.bundleContext = bc;
        this.configAdminReferences = configAdminReferences;
        State s = null;
        try {
            s = State.createOrReadState(bundleContext.getDataFile(State.FILE_NAME));
        } catch ( final ClassNotFoundException | IOException e ) {
            SystemLogger.error("Unable to read persisted state from " + State.FILE_NAME, e);
            s = new State();
        }
        this.state = s;
        this.tracker = new org.osgi.util.tracker.BundleTracker<>(this.bundleContext,
                Bundle.ACTIVE|Bundle.STARTING|Bundle.STOPPING|Bundle.RESOLVED|Bundle.INSTALLED,

                new BundleTrackerCustomizer<Bundle>() {

            @Override
            public Bundle addingBundle(final Bundle bundle, final BundleEvent event) {
                final int state = bundle.getState();
                if ( active &&
                    (state == Bundle.ACTIVE || state == Bundle.STARTING) ) {
                    SystemLogger.debug("Adding bundle " + getBundleIdentity(bundle) + " : " + getBundleState(state));
                    queue.enqueue(new Runnable() {

                        @Override
                        public void run() {
                            if ( processAddBundle(bundle) ) {
                                process();
                            }
                        }
                    });
                }
                return bundle;
            }

            @Override
            public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Bundle object) {
                this.addingBundle(bundle, event);
            }

            @Override
            public void removedBundle(final Bundle bundle, final BundleEvent event, final Bundle object) {
                final int state = bundle.getState();
                if ( active && state == Bundle.UNINSTALLED ) {
                    SystemLogger.debug("Removing bundle " + getBundleIdentity(bundle) + " : " + getBundleState(state));
                    queue.enqueue(new Runnable() {

                        @Override
                        public void run() {
                            try {
                                if ( processRemoveBundle(bundle.getBundleId()) ) {
                                    process();
                                }
                            } catch ( final IllegalStateException ise) {
                                SystemLogger.error("Error processing bundle " + getBundleIdentity(bundle), ise);
                            }
                        }
                    });
                }
            }

        });
    }

    public void configAdminAdded() {
        queue.enqueue(new Runnable() {

            @Override
            public void run() {
                process();
            }
        });
    }

    private String getBundleIdentity(final Bundle bundle) {
        if ( bundle.getSymbolicName() == null ) {
            return bundle.getBundleId() + " (" + bundle.getLocation() + ")";
        } else {
            return bundle.getSymbolicName() + ":" + bundle.getVersion() + " (" + bundle.getBundleId() + ")";
        }
    }

    private String getBundleState(int state) {
        switch ( state ) {
            case Bundle.ACTIVE : return "active";
            case Bundle.INSTALLED : return "installed";
            case Bundle.RESOLVED : return "resolved";
            case Bundle.STARTING : return "starting";
            case Bundle.STOPPING : return "stopping";
            case Bundle.UNINSTALLED : return "uninstalled";
        }
        return String.valueOf(state);
    }

    /**
     * Shut down the configurator
     */
    public void shutdown() {
        this.active = false;
        this.queue.stop();
        this.tracker.close();
    }

    /**
     * Start the configurator.
     */
    public void start() {
        // get the directory for storing binaries
        String dirPath = this.bundleContext.getProperty(ConfiguratorConstants.CONFIGURATOR_BINARIES);
        if ( dirPath != null ) {
            final File dir = new File(dirPath);
            if ( dir.exists() && dir.isDirectory() ) {
                BinUtil.binDirectory = dir;
            } else if ( dir.exists() ) {
                SystemLogger.error("Directory property is pointing at a file not a dir: " + dirPath + ". Using default path.");
            } else {
                try {
                    if ( dir.mkdirs() ) {
                        BinUtil.binDirectory = dir;
                    }
                } catch ( final SecurityException se ) {
                    // ignore
                }
                if ( BinUtil.binDirectory == null ) {
                    SystemLogger.error("Unable to create a directory at: " + dirPath + ". Using default path.");
                }
            }
        }
        if ( BinUtil.binDirectory == null ) {
            BinUtil.binDirectory = this.bundleContext.getDataFile("binaries" + File.separatorChar + ".check");
            BinUtil.binDirectory = BinUtil.binDirectory.getParentFile();
            BinUtil.binDirectory.mkdirs();
        }

        // before we start the tracker we process all available bundles and initial configuration
        final String initial = this.bundleContext.getProperty(ConfiguratorConstants.CONFIGURATOR_INITIAL);
        if ( initial == null ) {
            this.processRemoveBundle(-1);
        } else {
            // JSON or URLs ?
            final Set<String> hashes = new HashSet<>();
            final Map<String, String> files = new TreeMap<>();

            if ( !initial.trim().startsWith("{") ) {
                // URLs
                final String[] urls = initial.trim().split(",");
                for(final String urlString : urls) {
                    URL url = null;
                    try {
                        url = new URL(urlString);
                    } catch (final MalformedURLException e) {
                    }
                    if ( url != null ) {
                        try {
                            final String contents = JSONUtil.getResource(urlString, url);
                            files.put(urlString, contents);
                            hashes.add(Util.getSHA256(contents.trim()));
                        } catch ( final IOException ioe ) {
                            SystemLogger.error("Unable to read " + urlString, ioe);
                        }
                    }
                }
            } else {
                // JSON
                hashes.add(Util.getSHA256(initial.trim()));
                files.put(ConfiguratorConstants.CONFIGURATOR_INITIAL, initial);
            }
            if ( state.getInitialHashes() == null || !state.getInitialHashes().equals(hashes)) {
                if ( state.getInitialHashes() != null ) {
                    processRemoveBundle(-1);
                }
                final TypeConverter converter = new TypeConverter(null);
                final JSONUtil.Report report = new JSONUtil.Report();
                final List<ConfigurationFile> allFiles = new ArrayList<>();
                for(final Map.Entry<String, String> entry : files.entrySet()) {
                    final ConfigurationFile file = org.apache.felix.configurator.impl.json.JSONUtil.readJSON(converter, entry.getKey(), null, -1, entry.getValue(), report);
                    if ( file != null ) {
                        allFiles.add(file);
                    }
                }
                for(final String w : report.warnings) {
                    SystemLogger.warning(w);
                }
                for(final String e : report.errors) {
                    SystemLogger.error(e);
                }
                final BundleState bState = new BundleState();
                bState.addFiles(allFiles);
                for(final String pid : bState.getPids()) {
                    state.addAll(pid, bState.getConfigurations(pid));
                }
                state.setInitialHashes(hashes);
            }

        }

        final Bundle[] bundles = this.bundleContext.getBundles();
        final Set<Long> ids = new HashSet<>();
        for(final Bundle b : bundles) {
            ids.add(b.getBundleId());
            final int state = b.getState();
            if ( state == Bundle.ACTIVE || state == Bundle.STARTING ) {
                processAddBundle(b);
            }
        }
        for(final long id : state.getKnownBundleIds()) {
            if ( !ids.contains(id) ) {
                processRemoveBundle(id);
            }
        }
        this.process();
        this.tracker.open();
    }

    public boolean processAddBundle(final Bundle bundle) {
        final long bundleId = bundle.getBundleId();
        final long bundleLastModified = bundle.getLastModified();

        final Long lastModified = state.getLastModified(bundleId);
        if ( lastModified != null && lastModified.longValue() == bundleLastModified ) {
            // no changes, nothing to do
            return false;
        }

        BundleState config = null;
        try {
            final Set<String> paths = Util.isConfigurerBundle(bundle, this.bundleContext.getBundle().getBundleId());
            if ( paths != null ) {
                final JSONUtil.Report report = new JSONUtil.Report();
                config = JSONUtil.readConfigurationsFromBundle(new BinUtil.ResourceProvider() {

                    @Override
                    public String getIdentifier() {
                        return bundle.toString();
                    }

                    @Override
                    public URL getEntry(String path) {
                        return bundle.getEntry(path);
                    }

                    @Override
                    public long getBundleId() {
                        return bundle.getBundleId();
                    }

                    @Override
                    public Enumeration<URL> findEntries(String path, String filePattern) {
                        return bundle.findEntries(path, filePattern, false);
                    }
                }, paths, report);
                for(final String w : report.warnings) {
                    SystemLogger.warning(w);
                }
                for(final String e : report.errors) {
                    SystemLogger.error(e);
                }
            }
        } catch ( final IllegalStateException ise) {
            SystemLogger.error("Error processing bundle " + getBundleIdentity(bundle), ise);
        }
        if ( lastModified != null ) {
            processRemoveBundle(bundleId);
        }
        if ( config != null ) {
            for(final String pid : config.getPids()) {
                state.addAll(pid, config.getConfigurations(pid));
            }
            state.setLastModified(bundleId, bundleLastModified);
            return true;
        }
        return lastModified != null;
    }

    public boolean processRemoveBundle(final long bundleId) {
        if ( state.getLastModified(bundleId) != null ) {
            state.removeLastModified(bundleId);
            for(final String pid : state.getPids()) {
                final ConfigList configList = state.getConfigurations(pid);
                configList.uninstall(bundleId);
            }
            return true;
        }
        return false;
    }

    /**
     * Set or unset the coordinator service
     * @param coordinator The coordinator service or {@code null}
     */
    public void setCoordinator(final Object coordinator) {
        this.coordinator = coordinator;
    }

    /**
     * Process the state to activate/deactivate configurations
     */
    public void process() {
        final Object localCoordinator = this.coordinator;
        Object coordination = null;
        if ( localCoordinator != null ) {
            coordination = CoordinatorUtil.getCoordination(localCoordinator);
        }

        boolean retry = false;
        try {
            for(final String pid : state.getPids()) {
                final ConfigList configList = state.getConfigurations(pid);

                if ( configList.hasChanges() ) {
                    if ( process(configList) ) {
                        try {
                            State.writeState(this.bundleContext.getDataFile(State.FILE_NAME), state);
                        } catch ( final IOException ioe) {
                            SystemLogger.error("Unable to persist state to " + State.FILE_NAME, ioe);
                        }
                    } else {
                        retry = true;
                    }
                }
            }

        } finally {
            if ( coordination != null ) {
                CoordinatorUtil.endCoordination(coordination);
            }
        }
        if ( !retry ) {
            // check whether there is a stale config admin bundle id
            boolean changed = false;
            for(final Long bundleId : this.state.getBundleIdsUsingConfigAdmin()) {
                if ( this.state.getLastModified(bundleId) == null ) {
                    this.state.removeConfigAdminBundleId(bundleId);
                    changed = true;
                }
            }
            if ( changed ) {
                try {
                    State.writeState(this.bundleContext.getDataFile(State.FILE_NAME), state);
                } catch ( final IOException ioe) {
                    SystemLogger.error("Unable to persist state to " + State.FILE_NAME, ioe);
                }
            }
        }
    }

    /**
     * Process changes to a pid.
     * @param configList The config list
     * @return {@code true} if the change has been processed, {@code false} if a retry is required
     */
    public boolean process(final ConfigList configList) {
        Config toActivate = null;
        Config toDeactivate = null;

        for(final Config cfg : configList) {
            switch ( cfg.getState() ) {
                case INSTALL     : // activate if first found
                    if ( toActivate == null ) {
                        toActivate = cfg;
                    }
                    break;

                case IGNORED     : // same as installed
                case INSTALLED   : // check if we have to uninstall
                    if ( toActivate == null ) {
                        toActivate = cfg;
                    } else {
                        cfg.setState(ConfigState.INSTALL);
                    }
                    break;

                case UNINSTALL   : // deactivate if first found (we should only find one anyway)
                    if ( toDeactivate == null ) {
                       toDeactivate = cfg;
                    }
                    break;

                case UNINSTALLED : // nothing to do
                    break;
            }

        }
        // if there is a configuration to activate, we can directly activate it
        // without deactivating (reducing the changes of the configuration from two
        // to one)
        boolean noRetryNeeded = true;
        if ( toActivate != null && toActivate.getState() == ConfigState.INSTALL ) {
            noRetryNeeded = activate(configList, toActivate);
        }
        if ( toActivate == null && toDeactivate != null ) {
            noRetryNeeded = deactivate(configList, toDeactivate);
        }

        if ( noRetryNeeded ) {
            // remove all uninstall(ed) configurations
            final Iterator<Config> iter = configList.iterator();
            boolean foundInstalled = false;
            while ( iter.hasNext() ) {
                final Config cfg = iter.next();
                if ( cfg.getState() == ConfigState.UNINSTALL || cfg.getState() == ConfigState.UNINSTALLED ) {
                    if ( cfg.getFiles() != null ) {
                        for(final File f : cfg.getFiles()) {
                            f.delete();
                        }
                    }
                    iter.remove();
                } else if ( cfg.getState() == ConfigState.INSTALLED ) {
                    if ( foundInstalled ) {
                        cfg.setState(ConfigState.INSTALL);
                    } else {
                        foundInstalled = true;
                    }
                }
            }

            // mark as processed
            configList.setHasChanges(false);
        }
        return noRetryNeeded;
    }

    private ConfigurationAdmin getConfigurationAdmin(final long configAdminServiceBundleId) {
        ServiceReference<ConfigurationAdmin> ref = null;
        synchronized ( this.configAdminReferences ) {
            for(final ServiceReference<ConfigurationAdmin> r : this.configAdminReferences ) {
                final Bundle bundle = r.getBundle();
                if ( bundle != null && bundle.getBundleId() == configAdminServiceBundleId) {
                    ref = r;
                    break;
                }
            }
        }
        if ( ref != null ) {
            return this.bundleContext.getService(ref);
        }
        return null;
    }

    /**
     * Try to activate a configuration
     * Check policy and change count
     * @param configList The configuration list
     * @param cfg The configuration to activate
     * @return {@code true} if activation was successful
     */
    public boolean activate(final ConfigList configList, final Config cfg) {
        // check for configuration admin
        Long configAdminServiceBundleId = this.state.getConfigAdminBundleId(cfg.getBundleId());
        if ( configAdminServiceBundleId == null ) {
            final Bundle configBundle = cfg.getBundleId() == -1 ? this.bundleContext.getBundle() : this.bundleContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext().getBundle(cfg.getBundleId());
            // we check the state again, just to be sure (to avoid race conditions)
            if ( configBundle != null
                 && (configBundle.getState() == Bundle.STARTING || configBundle.getState() == Bundle.ACTIVE)) {
                if ( System.getSecurityManager() == null
                     || configBundle.hasPermission( new ServicePermission(ConfigurationAdmin.class.getName(), ServicePermission.GET)) ) {
                    try {
                        final BundleContext ctx = configBundle.getBundleContext();
                        if ( ctx != null ) {
                            final Collection<ServiceReference<ConfigurationAdmin>> refs = ctx.getServiceReferences(ConfigurationAdmin.class, null);
                            final List<ServiceReference<ConfigurationAdmin>> sortedRefs = new ArrayList<>(refs);
                            Collections.sort(sortedRefs);
                            for(int i=sortedRefs.size();i>0;i--) {
                                final ServiceReference<ConfigurationAdmin> r = sortedRefs.get(i-1);
                                synchronized ( this.configAdminReferences ) {
                                    if ( this.configAdminReferences.contains(r) ) {
                                        configAdminServiceBundleId = r.getBundle().getBundleId();
                                        break;
                                    }
                                }
                            }
                        }
                    } catch ( final IllegalStateException e) {
                        // this might happen if the config admin bundle gets deactivated while we use it
                        // we can ignore this and retry later on
                    } catch (final InvalidSyntaxException e) {
                        // this can never happen as we pass {@code null} as the filter
                    }
                }
            }
        }
        if ( configAdminServiceBundleId == null ) {
            // no configuration admin found, we have to retry
            return false;
        }
        final ConfigurationAdmin configAdmin = this.getConfigurationAdmin(configAdminServiceBundleId);
        if ( configAdmin == null ) {
            // getting configuration admin failed, we have to retry
            return false;
        }
        this.state.setConfigAdminBundleId(cfg.getBundleId(), configAdminServiceBundleId);

        boolean ignore = false;
        try {
            // get existing configuration - if any
            boolean update = false;
            Configuration configuration = ConfigUtil.getOrCreateConfiguration(configAdmin, cfg.getPid(), false);
            if ( configuration == null ) {
                // new configuration
                configuration = ConfigUtil.getOrCreateConfiguration(configAdmin, cfg.getPid(), true);
                update = true;
            } else {
                if ( cfg.getPolicy() == ConfigPolicy.FORCE ) {
                    update = true;
                } else {
                    if ( configList.getLastInstalled() == null
                         || configList.getChangeCount() != configuration.getChangeCount() ) {
                        ignore = true;
                    } else {
                        update = true;
                    }
                }
            }

            if ( update ) {
                configuration.updateIfDifferent(cfg.getProperties());
                cfg.setState(ConfigState.INSTALLED);
                configList.setChangeCount(configuration.getChangeCount());
                configList.setLastInstalled(cfg);
            }
        } catch (final InvalidSyntaxException | IOException e) {
            SystemLogger.error("Unable to update configuration " + cfg.getPid() + " : " + e.getMessage(), e);
            ignore = true;
        }
        if ( ignore ) {
            cfg.setState(ConfigState.IGNORED);
            configList.setChangeCount(-1);
            configList.setLastInstalled(null);
        }

        return true;
    }

    /**
     * Try to deactivate a configuration
     * Check policy and change count
     * @param cfg The configuration
     */
    public boolean deactivate(final ConfigList configList, final Config cfg) {
        final Long configAdminServiceBundleId = this.state.getConfigAdminBundleId(cfg.getBundleId());
        // check if configuration admin bundle is still available
        // if not or if we didn't record anything, we consider the configuration uninstalled
        final Bundle configBundle = configAdminServiceBundleId == null ? null : this.bundleContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext().getBundle(configAdminServiceBundleId);
        if ( configBundle != null ) {
            final ConfigurationAdmin configAdmin = this.getConfigurationAdmin(configAdminServiceBundleId);
            if ( configAdmin == null ) {
                // getting configuration admin failed, we have to retry
                return false;
            }

            try {
                final Configuration c = ConfigUtil.getOrCreateConfiguration(configAdmin, cfg.getPid(), false);
                if ( c != null ) {
                    if ( cfg.getPolicy() == ConfigPolicy.FORCE
                            || configList.getChangeCount() == c.getChangeCount() ) {
                        c.delete();
                    }
                }
            } catch (final InvalidSyntaxException | IOException e) {
                SystemLogger.error("Unable to remove configuration " + cfg.getPid() + " : " + e.getMessage(), e);
            }
        }
        cfg.setState(ConfigState.UNINSTALLED);
        configList.setChangeCount(-1);
        configList.setLastInstalled(null);

        return true;
    }
}
