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

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.Properties;

import org.apache.felix.cm.file.ConfigurationHandler;
import org.apache.felix.cm.json.Configurations;
import org.apache.sling.installer.api.InstallableResource;

/**
 * Internal resource is a private data object which wraps
 * an installable resource and is used to create a registered
 * resource.
 *
 * An internal resource has always:
 * - a resource type
 * - a digest
 *
 */
public class InternalResource extends InstallableResource {

    /**
     * Create an internal resource.
     * @throws IOException if something is wrong
     */
    public static InternalResource create(
            final String scheme,
            final InstallableResource resource)
    throws IOException {
        // installable resource has an id, a priority and either
        // an input stream or a dictionary
        InputStream is = resource.getInputStream();
        Dictionary<String, Object> dict = resource.getDictionary();

        // Handle deprecated types and map them to new types
        String type = resource.getType();
        if ( InstallableResource.TYPE_BUNDLE.equals(type) ) {
            type = InstallableResource.TYPE_FILE;
        } else if ( InstallableResource.TYPE_CONFIG.equals(type) ) {
            type = InstallableResource.TYPE_PROPERTIES;
        }

        // check for optional uri (only if type is file and digest is available)
        final String resourceUri = (dict != null
                                    && (type == null || InstallableResource.TYPE_FILE.equals(type))
                                    && resource.getDigest() != null
                                    && resource.getDigest().length() > 0) ?
                              (String)dict.get(InstallableResource.RESOURCE_URI_HINT) : null;
        // check if resourceUri is accessible
        boolean useResourceUri = resourceUri != null;
        if ( resourceUri != null ) {
            InputStream resourceUriIS = null;
            try {
                final URI uri = new URI(resourceUri);
                resourceUriIS = uri.toURL().openStream();
                // everything fine
            } catch (final Exception use) {
                useResourceUri = false;
            } finally {
                if ( resourceUriIS != null ) {
                    try {
                        resourceUriIS.close();
                    } catch (final IOException ignore) {
                        // ignore
                    }
                }
            }
        }

        if ( is != null &&
             (InstallableResource.TYPE_PROPERTIES.equals(type) ||
              ((type == null || InstallableResource.TYPE_FILE.equals(type)) && isConfigExtension(resource.getId())))) {
            try {
                dict = readDictionary(is, scheme, resource.getId());
            } catch (final IOException ioe) {
                throw (IOException)new IOException("Unable to read dictionary from input stream: " + resource.getId()).initCause(ioe);
            }
            is = null;
            useResourceUri = false;
        }

        File dataFile = null;
        final String digest;
        if ( is == null ) {
            // if input stream is null, properties is expected!
            type = (type != null ? type : InstallableResource.TYPE_PROPERTIES);
            // we always compute a digest
            digest = FileDataStore.computeDigest(dict);
        } else {
            type = (type != null ? type : InstallableResource.TYPE_FILE);
            if ( resourceUri != null && useResourceUri ) {
                digest = resource.getDigest();
            } else {
                final String url = scheme + ':' + resource.getId();
                // if input stream is not null, file is expected!
                dataFile = FileDataStore.SHARED.createNewDataFile(is,
                        url,
                        resource.getDigest(),
                        resource.getType());
                if (resource.getDigest() != null && resource.getDigest().length() > 0) {
                    digest = resource.getDigest();
                } else {
                    digest = FileDataStore.computeDigest(dataFile);
                    FileDataStore.SHARED.updateDigestCache(url, dataFile, digest);
                }
            }
        }
        return new InternalResource(scheme,
                resource.getId(),
                is,
                dict,
                type,
                digest,
                resource.getPriority(),
                dataFile,
                useResourceUri ? resourceUri : null);
    }

    /** The unique resource url. */
    private final String url;

    /** The data file (if copied) */
    private File dataFile;

    /** The resource uri */
    private final String resourceUri;

    public InternalResource(
            final String scheme,
            final String id,
            final InputStream is,
            final Dictionary<String, Object> dict,
            final String type,
            final String digest,
            final Integer priority,
            final File dataFile,
            final String resourceUri) {
        super(id, is, dict, digest, type, priority);
        this.url = scheme + ':' + id;
        this.dataFile = dataFile;
        this.resourceUri = resourceUri;
    }

    /** The unique url of the resource. */
    public String getURL() {
        return this.url;
    }

    /**
     * Copy given Dictionary
     */
    public Dictionary<String, Object> getPrivateCopyOfDictionary() {
        final Dictionary<String, Object> d = this.getDictionary();
        if ( d == null ) {
            return null;
        }

        final Dictionary<String, Object> result = new Hashtable<>();
        final Enumeration<String> e = d.keys();
        while(e.hasMoreElements()) {
            final String key = e.nextElement();
            result.put(key, d.get(key));
        }
        return result;
    }

    /**
     * Copy the given file and return it.
     */
    public File getPrivateCopyOfFile() {
        return this.dataFile;
    }

    /**
     * Set the data file.
     */
    public void setPrivateCopyOfFile(final File file) {
        this.dataFile = file;
    }

    /**
     * Return the resource uri (or null)
     */
    public String getResourceUri() {
        return this.resourceUri;
    }

    /**
     * Read dictionary from an input stream.
     * We use the same logic as Apache Felix FileInstall here:
     * - *.cfg files are treated as property files
     * - *.config files are handled by the Apache Felix ConfigAdmin file reader
     * And all *.json files are read using code from Apache Felix Configurator
     * @param is
     * @param extension
     * @throws IOException
     */
    private static Dictionary<String, Object> readDictionary(
            final InputStream is, final String scheme, final String id)
    throws IOException {
        if ( id.endsWith(".cfg.json") ) {
            String configId;
            int pos = id.lastIndexOf('/');
            if ( pos == -1 ) {
                configId = id;
            } else {
                configId = id.substring(pos + 1);
            }
            pos = configId.indexOf('-');
            if ( pos != -1 ) {
                configId = configId.substring(0, pos).concat("~").concat(configId.substring(pos+1));
            }
            configId = removeConfigExtension(configId);

            // read from input stream
            try(final Reader reader =  new InputStreamReader(is, "UTF-8")) {
                return Configurations.buildReader()
                        .withIdentifier(configId).build(reader).readConfiguration();

            }

        } else {
            final Hashtable<String, Object> ht = new Hashtable<>();

            try (final BufferedInputStream in = new BufferedInputStream(is)) {

                if (id.endsWith(".config") ) {
                    // check for initial comment line
                    in.mark(256);
                    final int firstChar = in.read();
                    if ( firstChar == '#' ) {
                        int b;
                        while ((b = in.read()) != '\n' ) {
                            if ( b == -1 ) {
                                throw new IOException("Unable to read configuration.");
                            }
                        }
                    } else {
                        in.reset();
                    }
                    @SuppressWarnings("unchecked")
                    final Dictionary<String, Object> config = ConfigurationHandler.read(in);
                    final Enumeration<String> i = config.keys();
                    while ( i.hasMoreElements() ) {
                        final String key = i.nextElement();
                        ht.put(key, config.get(key));
                    }
                } else {
                    final Properties p = new Properties();
                    in.mark(1);
                    boolean isXml = in.read() == '<';
                    in.reset();
                    if (isXml) {
                        p.loadFromXML(in);
                    } else {
                        p.load(in);
                    }
                    final Enumeration<Object> i = p.keys();
                    while ( i.hasMoreElements() ) {
                        final Object key = i.nextElement();
                        ht.put(key.toString(), p.get(key));
                    }
                }
            }
            return ht;
        }
    }

    private static final List<String> EXTENSIONS = Arrays.asList(".config", ".properties", ".cfg", ".cfg.json");
    private static boolean isConfigExtension(final String url) {
        for(final String ext : EXTENSIONS) {
            if ( url.endsWith(ext) ) {
                return true;
            }
        }
        return false;
    }

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