/*
 * 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.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.propertytypes.ServiceDescription;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** This is the basic implementation of the sling settings service. */
@Component
@Designate(ocd = SlingSettingsServiceImpl.Configuration.class)
@ServiceDescription("Apache Sling Settings Service")
public class SlingSettingsServiceImpl
        implements SlingSettingsService {

    /** 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;

    private Configuration configuration;

    /** 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";

    @ObjectClassDefinition(id = "org.apache.sling.settings.impl.SlingSettingsServiceImpl", name = "Apache Sling Settings Service", 
            description = "The settings service manages some basic settings of Sling like run modes or information about the current instance.")
    static @interface Configuration {
        @AttributeDefinition(name = "Instance Name", description = "A human readable name for the current instance.")
        String sling_name();

        @AttributeDefinition(name = "Instance Description", description = "A human readable description for the current instance.")
        String sling_description();
    }

    /** Create the service and search the Sling home urls and get/create a sling id. Setup run modes
     * 
     * @param context The bundle context */
    @Activate
    public SlingSettingsServiceImpl(final Configuration configuration, final BundleContext context) {
        this.configuration = configuration;
        this.setupSlingHome(context);
        this.setupSlingId(context);
        this.setupRunModes(context);
    }
   
    /**
     * Constructor only to be used from tests
     * @param runModes
     */
    public SlingSettingsServiceImpl(String runModes) {
        this.runModes = parseRunModes(runModes);
    }

    /** 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);
            }
        }
    }

    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;
    }

    private Set<String> parseRunModes(String runModes) {
        final Set<String> modesSet = new HashSet<>();
        final String[] modes = runModes.split(",");
        for (int i = 0; i < modes.length; i++) {
            modesSet.add(modes[i].trim());
        }
        return modesSet;
    }

    /** Set up run modes. */
    private void setupRunModes(final BundleContext context) {
        final Set<String> modesSet;

        // check configuration property first
        final String prop = context.getProperty(RUN_MODES_PROPERTY);
        if (prop != null && prop.trim().length() > 0) {
            modesSet = parseRunModes(prop);
        } else {
            modesSet = new HashSet<>();
        }

        // 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) */
    @Override
    public String getAbsolutePathWithinSlingHome(final String relativePath) {
        return new File(slingHome, relativePath).getAbsolutePath();
    }

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

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

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

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

    @Override
    public int getBestRunModeMatchCountFromSpec(String spec) {
        return getBestRunModeMatchCountFromSpec(spec, runModes);
    }

    static int getBestRunModeMatchCountFromSpec(String spec, Collection<String> activeRunModes) {
        int numMatchingRunModes = 0;
        // 1. support OR
        for (String discjunctivePart : spec.split(Pattern.quote(RUN_MODE_SPEC_OR_SEPARATOR))) {
            int newNumMatchingRunModes = getBestRunModeMatchCountFromConjunctions(discjunctivePart, activeRunModes);
            if (newNumMatchingRunModes > numMatchingRunModes) {
                numMatchingRunModes = newNumMatchingRunModes;
            }
        }
        return numMatchingRunModes;
    }

    static int getBestRunModeMatchCountFromConjunctions(String conjunctions, Collection<String> activeRunModes) {
        int numMatchingRunModes = 0;
        // 2. support AND
        for (String conjunctivePart : conjunctions.split(Pattern.quote(RUN_MODE_SPEC_AND_SEPARATOR))) {
            // 3. support NOT operator
            if (conjunctivePart.startsWith(RUN_MODE_SPEC_NOT_PREFIX)) {
                if (activeRunModes.contains(conjunctivePart.substring(RUN_MODE_SPEC_NOT_PREFIX.length()))) {
                    return 0;
                }
            } else {
                if (!activeRunModes.contains(conjunctivePart)) {
                    return 0;
                }
            }
            numMatchingRunModes++;
        }
        return numMatchingRunModes;
    }

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

    /** @see org.apache.sling.settings.SlingSettingsService#getSlingDescription() */
    @Override
    public String getSlingDescription() {
        String desc = configuration.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 */
    @Modified
    public void update(final Configuration configuration) {
        // TODO is configuration thread safe i.e. new object per call?
        this.configuration = configuration;
    }
}
