/*
 * 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 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 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) {
        this.setupSlingProps(context);
        this.setupSlingHome(context);
        this.setupSlingId(context);

        this.setupRunModes(context);

    }

    /**
     * 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);
            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 = SlingIdUtil.createSlingId();
            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 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
        // 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
        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());
                }
            }
        }
    }
}
