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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.sling.launchpad.api.StartupHandler;
import org.apache.sling.launchpad.api.StartupMode;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is the basic implementation of the sling settings service.
 */
public class SlingSettingsServiceImpl
    implements SlingSettingsService {

    /** Property containing the sling name. */
    private static final String SLING_NAME = "sling.name";

    /** Property containing the sling description. */
    private static final String SLING_DESCRIPTION = "sling.description";

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

    /** The sling instance id. */
    private String slingId;

    /** The sling home */
    private String slingHome;

    /** The sling home url */
    private URL slingHomeUrl;

    /** The set of run modes .*/
    private Set<String> runModes;

    /** The name of the data file holding the sling id. */
    private static final String ID_FILE = "sling.id.file";

    /** The name of the data file holding install run mode options */
    private static final String OPTIONS_FILE = "sling.options.file";

    /** The length in bytes of a sling identifier */
    private static final int SLING_ID_LENGTH = 36;

    /** The properties for name, description. */
    private final Map<String, String> slingProps = new HashMap<String, String>();

    /**
     * Create the service and search the Sling home urls and
     * get/create a sling id.
     * Setup run modes
     * @param context The bundle context
     */
    public SlingSettingsServiceImpl(final BundleContext context,
            final StartupHandler handler) {
        this.setupSlingProps(context);
        this.setupSlingHome(context);
        this.setupSlingId(context);

        final StartupMode mode = handler.getMode();
        logger.debug("Settings: Using startup mode : {}", mode);

        this.setupRunModes(context, mode);

    }

    /**
     * Get sling home and sling home URL
     */
    private void setupSlingHome(final BundleContext context) {
        this.slingHome = context.getProperty(SLING_HOME);
        final String url = context.getProperty(SLING_HOME_URL);
        if ( url != null ) {
            try {
                this.slingHomeUrl = new URL(url);
            } catch (MalformedURLException e) {
                logger.error("Sling home url is not a url: {}", url);
            }
        }
    }

    /**
     * Get / create sling id
     */
    private void setupSlingId(final BundleContext context) {
        // try to read the id from the id file first
        final File idFile = context.getDataFile(ID_FILE);
        if ( idFile == null ) {
            // the osgi framework does not support storing something in the file system
            throw new RuntimeException("Unable to read from bundle data file.");
        }

        try {
            slingId = SlingIdUtil.readSlingId(idFile, SLING_ID_LENGTH);
            logger.info("Read Sling ID {} from file {}", slingId, idFile);
        } catch (final Throwable t) {
            logger.error("Failed reading Sling ID from file " + idFile, t);
        }

        // no sling id yet or failure to read file: create an id and store
        if (slingId == null) {
            slingId = UUID.randomUUID().toString();
            logger.info("Created new Sling ID {}", slingId);
            try {
                SlingIdUtil.writeSlingId(idFile, slingId);
            } catch (final Throwable t) {
                logger.error("Failed writing Sling ID to file " + idFile, t);
            }
        }
    }

    /**
     * Get / create sling id
     */
    private void setupSlingProps(final BundleContext context) {
        synchronized ( this.slingProps ) {
            if ( this.slingProps.get(SLING_NAME) == null && context.getProperty(SLING_NAME) != null ) {
                this.slingProps.put(SLING_NAME, context.getProperty(SLING_NAME));
            }
            if ( this.slingProps.get(SLING_DESCRIPTION) == null && context.getProperty(SLING_DESCRIPTION) != null ) {
                this.slingProps.put(SLING_DESCRIPTION, context.getProperty(SLING_DESCRIPTION));
            }
        }
    }

    static final class Options implements Serializable {
        private static final long serialVersionUID = 1L;
        String[] modes;
        String   selected;
    }

    private List<Options> handleOptions(final Set<String> modesSet, final String propOptions) {
        final List<Options> optionsList = new ArrayList<Options>();
        if ( propOptions != null && propOptions.trim().length() > 0 ) {

            final String[] options = propOptions.trim().split("\\|");
            for(final String opt : options) {
                String selected = null;
                final String[] modes = opt.trim().split(",");
                for(int i=0; i<modes.length; i++) {
                    modes[i] = modes[i].trim();
                    if ( selected != null ) {
                        modesSet.remove(modes[i]);
                    } else {
                        if ( modesSet.contains(modes[i]) ) {
                            selected = modes[i];
                        }
                    }
                }
                if ( selected == null ) {
                    selected = modes[0];
                    modesSet.add(modes[0]);
                }
                final Options o = new Options();
                o.selected = selected;
                o.modes = modes;
                optionsList.add(o);
            }
        }
        return optionsList;
    }

    /**
     * Set up run modes.
     */
    private void setupRunModes(final BundleContext context,
            final StartupMode startupMode) {
        final Set<String> modesSet = new HashSet<String>();

        // check configuration property first
        final String prop = context.getProperty(RUN_MODES_PROPERTY);
        if (prop != null && prop.trim().length() > 0) {
            final String[] modes = prop.split(",");
            for(int i=0; i < modes.length; i++) {
                modesSet.add(modes[i].trim());
            }
        }

        //  handle configured options
        this.handleOptions(modesSet, context.getProperty(RUN_MODE_OPTIONS));

        // handle configured install options
        if ( startupMode != StartupMode.INSTALL ) {
            // read persisted options if restart or update
            final List<Options> storedOptions = readOptions(context);
            if ( storedOptions != null ) {
                for(final Options o : storedOptions) {
                    for(final String m : o.modes) {
                        modesSet.remove(m);
                    }
                    modesSet.add(o.selected);
                }
            }
        }

        // now install options
        if ( startupMode != StartupMode.RESTART ) {
            // process new install options if install or update
            final List<Options> optionsList = this.handleOptions(modesSet, context.getProperty(RUN_MODE_INSTALL_OPTIONS));
            // and always save new install options
            writeOptions(context, optionsList);
        }

        // make the set unmodifiable and synced
        // we probably don't need a synced set as it is read only
        this.runModes = Collections.synchronizedSet(Collections.unmodifiableSet(modesSet));
        if ( this.runModes.size() > 0 ) {
            logger.info("Active run modes: {}", this.runModes);
        } else {
            logger.info("No run modes active");
        }
    }


    @SuppressWarnings("unchecked")
    private List<Options> readOptions(final BundleContext context) {
        List<Options> optionsList = null;
        final File file = context.getDataFile(OPTIONS_FILE);
        if ( file.exists() ) {
            FileInputStream fis = null;
            ObjectInputStream ois = null;
            try {
                fis = new FileInputStream(file);
                ois = new ObjectInputStream(fis);

                optionsList = (List<Options>) ois.readObject();
            } catch ( final IOException ioe ) {
                throw new RuntimeException("Unable to read from options data file.", ioe);
            } catch (ClassNotFoundException cnfe) {
                throw new RuntimeException("Unable to read from options data file.", cnfe);
            } finally {
                if ( ois != null ) {
                    try { ois.close(); } catch ( final IOException ignore) {}
                }
                if ( fis != null ) {
                    try { fis.close(); } catch ( final IOException ignore) {}
                }
            }
        }
        return optionsList;
    }

    void writeOptions(final BundleContext context, final List<Options> optionsList) {
        final File file = context.getDataFile(OPTIONS_FILE);
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(optionsList);
        } catch ( final IOException ioe ) {
            throw new RuntimeException("Unable to write to options data file.", ioe);
        } finally {
            if ( oos != null ) {
                try { oos.close(); } catch ( final IOException ignore) {}
            }
            if ( fos != null ) {
                try { fos.close(); } catch ( final IOException ignore) {}
            }
        }
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getAbsolutePathWithinSlingHome(String)
     */
    public String getAbsolutePathWithinSlingHome(final String relativePath) {
        return new File(slingHome, relativePath).getAbsolutePath();
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getSlingId()
     */
    public String getSlingId() {
        return this.slingId;
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getSlingHome()
     */
    public URL getSlingHome() {
        return this.slingHomeUrl;
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getSlingHomePath()
     */
    public String getSlingHomePath() {
        return this.slingHome;
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getRunModes()
     */
    public Set<String> getRunModes() {
        return this.runModes;
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getSlingName()
     */
    public String getSlingName() {
        synchronized ( this.slingProps ) {
            String name = this.slingProps.get(SLING_NAME);
            if ( name == null ) {
                name = "Instance " + this.slingId; // default
            }
            return name;
        }
    }

    /**
     * @see org.apache.sling.settings.SlingSettingsService#getSlingDescription()
     */
    public String getSlingDescription() {
        synchronized ( this.slingProps ) {
            String desc = this.slingProps.get(SLING_DESCRIPTION);
            if ( desc == null ) {
                desc = "Instance with id " + this.slingId + " and run modes " + this.getRunModes(); // default
            }
            return desc;
        }
    }

    /**
     * Update the configuration of this service
     */
    public void update(final Dictionary<String, Object> properties) {
        if ( properties != null ) {
            synchronized ( this.slingProps ) {
                if ( properties.get(SLING_NAME) != null ) {
                    this.slingProps.put(SLING_NAME, properties.get(SLING_NAME).toString());
                }
                if ( properties.get(SLING_DESCRIPTION) != null ) {
                    this.slingProps.put(SLING_DESCRIPTION, properties.get(SLING_DESCRIPTION).toString());
                }
            }
        }
    }
}
