/*
 * 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.installer.factories.configuration.impl;

import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.ResourceChangeListener;
import org.apache.sling.installer.api.tasks.ChangeStateTask;
import org.apache.sling.installer.api.tasks.InstallTask;
import org.apache.sling.installer.api.tasks.InstallTaskFactory;
import org.apache.sling.installer.api.tasks.RegisteredResource;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.installer.api.tasks.ResourceTransformer;
import org.apache.sling.installer.api.tasks.TaskResource;
import org.apache.sling.installer.api.tasks.TaskResourceGroup;
import org.apache.sling.installer.api.tasks.TransformationResult;
import org.apache.sling.installer.factories.configuration.ConfigurationConstants;
import org.apache.sling.installer.factories.configuration.ConfigurationMerger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationEvent;
import org.osgi.service.cm.ConfigurationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Task creator for configurations.
 */
public class ConfigTaskCreator
    implements InstallTaskFactory, ConfigurationListener, ResourceTransformer {

    /** Logger. */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /** Configuration admin. */
    private final ConfigurationAdmin configAdmin;

    /** Resource change listener. */
    private final ResourceChangeListener changeListener;

    /** Info Provider */
    private final ConfigurationMerger configMerger;

    public ConfigTaskCreator(final ResourceChangeListener listener,
            final ConfigurationAdmin configAdmin,
            final ConfigurationMerger configMerger) {
        this.changeListener = listener;
        this.configAdmin = configAdmin;
        this.configMerger = configMerger;
    }

    public ServiceRegistration<?> register(final BundleContext bundleContext) {
        final Hashtable<String, String> props = new Hashtable<>();
        props.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Configuration Install Task Factory");
        props.put(Constants.SERVICE_VENDOR, ServicesListener.VENDOR);
        props.put(InstallTaskFactory.NAME, "org.osgi.service.cm");
        props.put(ResourceTransformer.NAME, "org.osgi.service.cm");

        final String [] serviceInterfaces = {
                InstallTaskFactory.class.getName(),
                ConfigurationListener.class.getName(),
                ResourceTransformer.class.getName()
        };
        final ServiceRegistration<?> reg = bundleContext.registerService(serviceInterfaces, this, props);
        this.logger.info("OSGi Configuration support for OSGi installer active, default location={}, merge schemes={}", 
                Activator.DEFAULT_LOCATION, Activator.MERGE_SCHEMES);
        return reg;
    }

    /**
     * Create a task to install or uninstall a configuration.
     *
	 * @see org.apache.sling.installer.api.tasks.InstallTaskFactory#createTask(org.apache.sling.installer.api.tasks.TaskResourceGroup)
	 */
	@Override
    public InstallTask createTask(final TaskResourceGroup group) {
        final TaskResource toActivate = group.getActiveResource();
        if ( !toActivate.getType().equals(InstallableResource.TYPE_CONFIG) ) {
            return null;
        }

        final InstallTask result;
		if (toActivate.getState() == ResourceState.UNINSTALL) {
            // if this is an uninstall, check if we have to install an older version
            // in this case we should do an update instead of uninstall/install (!)
            final TaskResource second = group.getNextActiveResource();
            if ( second != null
                && ( second.getState() == ResourceState.IGNORED || second.getState() == ResourceState.INSTALLED || second.getState() == ResourceState.INSTALL )
                && ( second.getDictionary() == null || second.getDictionary().get(InstallableResource.RESOURCE_IS_TEMPLATE) == null)) {
                result = new ChangeStateTask(group, ResourceState.UNINSTALLED);
            } else {
                result = new ConfigRemoveTask(group, this.configAdmin);
            }
		} else {
	        result = new ConfigInstallTask(group, this.configAdmin);
		}
		return result;
	}

    /**
     * @see org.osgi.service.cm.ConfigurationListener#configurationEvent(org.osgi.service.cm.ConfigurationEvent)
     */
    @Override
    public void configurationEvent(final ConfigurationEvent event) {
        synchronized ( Coordinator.SHARED ) {
            if ( event.getType() == ConfigurationEvent.CM_DELETED ) {
                final Coordinator.Operation op = Coordinator.SHARED.get(event.getPid(), event.getFactoryPid(), true);
                if ( op == null ) {
                    this.changeListener.resourceRemoved(InstallableResource.TYPE_CONFIG, event.getPid());
                } else {
                    this.logger.debug("Ignoring configuration event for {}:{}", event.getPid(), event.getFactoryPid());
                }
            } else if ( event.getType() == ConfigurationEvent.CM_UPDATED ) {
                try {
                    // we just need to pass in the pid as we're using named factory configs
                    final Configuration config = ConfigUtil.getConfiguration(configAdmin,
                            null,
                            event.getPid());
                    final Coordinator.Operation op = Coordinator.SHARED.get(event.getPid(), event.getFactoryPid(), false);
                    if ( config != null && op == null ) {
                        final boolean persist = ConfigUtil.toBoolean(config.getProperties().get(ConfigurationConstants.PROPERTY_PERSISTENCE), true);

                        final Dictionary<String, Object> dict = ConfigUtil.cleanConfiguration(config.getProperties());
                        final Map<String, Object> attrs = new HashMap<>();
                        if ( !persist ) {
                            attrs.put(ResourceChangeListener.RESOURCE_PERSIST, Boolean.FALSE);
                        }
                        attrs.put(Constants.SERVICE_PID, event.getPid());
                        attrs.put(InstallableResource.RESOURCE_URI_HINT, event.getPid());
                        if ( config.getBundleLocation() != null ) {
                            attrs.put(InstallableResource.INSTALLATION_HINT, config.getBundleLocation());
                        }
                        // Factory?
                        if (event.getFactoryPid() != null) {
                            attrs.put(ConfigurationAdmin.SERVICE_FACTORYPID, event.getFactoryPid());
                        }

                        configMerger.removeDefaultProperties(event.getPid(), dict);
                        this.changeListener.resourceAddedOrUpdated(InstallableResource.TYPE_CONFIG, event.getPid(), null, dict, attrs);

                    } else {
                        this.logger.debug("Ignoring configuration event for {}:{}", event.getPid(), event.getFactoryPid());
                    }
                } catch ( final Exception ignore) {
                    // ignore for now
                }
            }
        }
    }

    /**
     * @see org.apache.sling.installer.api.tasks.ResourceTransformer#transform(org.apache.sling.installer.api.tasks.RegisteredResource)
     */
    @Override
    public TransformationResult[] transform(final RegisteredResource resource) {
        if ( resource.getType().equals(InstallableResource.TYPE_PROPERTIES) ) {
            return checkConfiguration(resource);
        }
        return null;
    }

    private static String getResourceId(final String rawUrl) {
        final String url = separatorsToUnix(rawUrl);
        int pos = url.lastIndexOf('/');
        if ( pos == -1 ) {
            pos = url.indexOf(':');
        }

        final String lastIdPart;
        if ( pos != -1 ) {
            lastIdPart = url.substring(pos + 1);
        } else {
            lastIdPart = url;
        }
        return lastIdPart;
    }

    /**
     * Check if the registered resource is a configuration
     * @param resource The resource
     */
    private TransformationResult[] checkConfiguration(final RegisteredResource resource) {
        final String lastIdPart = getResourceId(resource.getURL());

        // remove extension if known
        final String pid = removeConfigExtension(lastIdPart);

        // split pid and factory pid alias
        final Map<String, Object> attr = new HashMap<>();
        final String factoryPid;
        final String configPid;
        int n = pid.indexOf('~');
        if ( n == -1 ) {
            n = pid.indexOf('-');
        }
        if (n > 0) {
            configPid = pid.substring(n + 1);
            factoryPid = pid.substring(0, n);
            attr.put(ConfigurationAdmin.SERVICE_FACTORYPID, factoryPid);
        } else {
            factoryPid = null;
            configPid = pid;
        }
        attr.put(Constants.SERVICE_PID, configPid);

        final TransformationResult tr = new TransformationResult();
        final String id = (factoryPid == null ? configPid : ConfigUtil.getPIDOfFactoryPID(factoryPid, configPid));
        tr.setId(id);
        tr.setResourceType(InstallableResource.TYPE_CONFIG);
        tr.setAttributes(attr);

        return new TransformationResult[] {tr};
    }

    private static final List<String> EXTENSIONS = Arrays.asList(".config", ".properties", ".cfg", ".cfg.json");
    private static String removeConfigExtension(final String id) {
        for(final String ext : EXTENSIONS) {
            if ( id.endsWith(ext) ) {
                return id.substring(0, id.length() - ext.length());
            }
        }
        return id;
    }

    /**
     * Converts all separators to the Unix separator of forward slash.
     *
     * @param path  the path to be changed, null ignored
     * @return the updated path
     */
    private static String separatorsToUnix(final String path) {
        if (path == null || path.indexOf('\\') == -1) {
            return path;
        }
        return path.replace('\\', '/');
    }
}
