/*
 * 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.BinaryManager;
import org.apache.felix.configurator.impl.json.JSONUtil;
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 JSONUtil.Report report = new JSONUtil.Report();
                final BinaryManager converter = new BinaryManager(null, report);
                final List<ConfigurationFile> allFiles = new ArrayList<>();
                for(final Map.Entry<String, String> entry : files.entrySet()) {
                    final ConfigurationFile file = 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;
    }
}
