/*
 * 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.ace.repository.impl;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;

import org.apache.ace.repository.Repository;
import org.apache.ace.repository.RepositoryReplication;
import org.apache.ace.repository.impl.constants.RepositoryConstants;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.service.Service;
import org.osgi.framework.BundleContext;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.service.log.LogService;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
import org.osgi.service.prefs.PreferencesService;

/**
 * A <code>ManagedServiceFactory</code> responsible for creating a (<code>Replication</code>)<code>Repository</code>
 * instance for each valid configuration that is received from the <code>ConfigurationAdmin</code>.
 */
public class RepositoryFactory implements ManagedServiceFactory {

    private volatile LogService m_log;                     /* injected by dependency manager */
    private volatile BundleContext m_context;              /* injected by dependency manager */
    private volatile PreferencesService m_prefsService;    /* injected by dependency manager */

    private File m_tempDir;
    private File m_baseDir;
    private Preferences m_prefs;
    private final DependencyManager m_manager;
    private final Map<String, Service> m_instances = new HashMap<String, Service>();

    public RepositoryFactory(DependencyManager manager) {
        m_manager = manager;
    }

    public synchronized void deleted(String pid) {
        // pull service
        Service service = m_instances.remove(pid);
        if (service != null) {
            m_manager.remove(service);
        }

        // remove persisted data
        File dir = new File(m_baseDir, pid);
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (int i = 0; (files != null) && (i < files.length); i++) {
                files[i].delete();
            }
            if (!dir.delete()) {
                m_log.log(LogService.LOG_WARNING, "Unable to clean up files ( in " + dir.getAbsolutePath() + ") after removing repository");
            }
        }
        try {
            m_prefs.node(pid).removeNode();
            m_prefs.sync();
        }
        catch (BackingStoreException e) {
            // Not much we can do
        }
    }

    public String getName() {
        return "RepositoryFactory";
    }

    public synchronized void init() {
        m_tempDir = m_context.getDataFile("tmp");
        if ((m_tempDir != null) && !m_tempDir.isDirectory() && !m_tempDir.mkdirs()) {
            throw new IllegalArgumentException("Unable to create temp directory (" + m_tempDir.getAbsolutePath() + ")");
        }
        m_baseDir = m_context.getDataFile("repos");
        if ((m_baseDir != null) && !m_baseDir.isDirectory() && !m_baseDir.mkdirs()) {
            throw new IllegalArgumentException("Unable to create base directory (" + m_baseDir.getAbsolutePath() + ")");
        }
    }

    /**
     * Creates a new instance if the supplied dictionary contains a valid configuration. A configuration is valid if
     * <code>RepositoryConstants.REPOSITORY_NAME</code> and <code>RepositoryConstants.REPOSITORY_CUSTOMER</code> properties
     * are present, not empty and the combination of the two is unique in respect to other previously created instances.
     * Finally a property <code>RepositoryConstants.REPOSITORY_MASTER</code> should be present and be either <code>true</code>
     * or <code>false</code>.
     *
     * @param pid A unique identifier for the instance, generated by <code>ConfigurationAdmin</code> normally.
     * @param dict The configuration properties for the instance, see description above.
     * @throws ConfigurationException If any of the above explanation fails <b>or</b>when there is an internal error creating the repository.
     */
    @SuppressWarnings("unchecked")
    public synchronized void updated(String pid, Dictionary dict) throws ConfigurationException {
        String name = (String) dict.get(RepositoryConstants.REPOSITORY_NAME);
        if ((name == null) || "".equals(name)) {
            throw new ConfigurationException(RepositoryConstants.REPOSITORY_NAME, "Repository name has to be specified.");
        }

        String customer = (String) dict.get(RepositoryConstants.REPOSITORY_CUSTOMER);
        if ((customer == null) || "".equals(customer)) {
            throw new ConfigurationException(RepositoryConstants.REPOSITORY_CUSTOMER, "Repository customer has to be specified.");
        }

        String master = (String) dict.get(RepositoryConstants.REPOSITORY_MASTER);
        if (!("false".equalsIgnoreCase(master.trim()) || "true".equalsIgnoreCase(master.trim()))) {
            throw new ConfigurationException(RepositoryConstants.REPOSITORY_MASTER, "Have to specify whether the repository is the master or a slave.");
        }
        boolean isMaster = Boolean.parseBoolean(master);

        String initialContents = (String) dict.get(RepositoryConstants.REPOSITORY_INITIAL_CONTENT);

        if (m_prefs == null) {
            m_prefs = m_prefsService.getSystemPreferences();
        }

        String[] nodes;
        try {
            nodes = m_prefs.childrenNames();
        }
        catch (BackingStoreException e) {
            throw new ConfigurationException("none", "Internal error while validating configuration.");
        }
        for (int i = 0; i < nodes.length; i++) {
            Preferences node = m_prefs.node(nodes[i]);
            if (name.equalsIgnoreCase(node.get(RepositoryConstants.REPOSITORY_NAME, "")) && name.equalsIgnoreCase(node.get(RepositoryConstants.REPOSITORY_CUSTOMER, ""))) {
                throw new ConfigurationException("name and customer", "Name and customer combination already exists");
            }
        }

        Preferences node = m_prefs.node(pid);
        node.put(RepositoryConstants.REPOSITORY_NAME, name);
        node.put(RepositoryConstants.REPOSITORY_CUSTOMER, customer);

        Service service = m_instances.get(pid);
        if (service == null) {
            // new instance
            File dir = new File(m_baseDir, pid);
            RepositoryImpl store = new RepositoryImpl(dir, m_tempDir, isMaster);
            if ((initialContents != null) && isMaster) {
                try {
                    store.commit(new ByteArrayInputStream(initialContents.getBytes()), 0);
                }
                catch (IOException e) {
                    m_log.log(LogService.LOG_ERROR, "Unable to set initial contents of the repository.", e);
                }
            }
            service = m_manager.createComponent()
                .setInterface(new String[] {RepositoryReplication.class.getName(), Repository.class.getName()}, dict)
                .setImplementation(store)
                .add(m_manager.createServiceDependency().setService(LogService.class).setRequired(false));
            m_manager.add(service);
            m_instances.put(pid, service);
        } else {
            // update existing instance
            RepositoryImpl store = (RepositoryImpl) service.getService();
            store.updated(isMaster);
        }
    }
}
