/*
 * 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.commons.mime.internal;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.sling.commons.mime.MimeTypeProvider;
import org.apache.sling.commons.mime.MimeTypeService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
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;

/**
 * The <code>MimeTypeServiceImpl</code> is the official implementation of the
 * {@link MimeTypeService} interface.
 */
@Component(service = MimeTypeService.class,
    property = {
            Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
            Constants.SERVICE_DESCRIPTION + "=Apache Sling Commons MIME Type Service"
    })
@Designate(ocd = MimeTypeServiceImpl.Config.class)
public class MimeTypeServiceImpl implements MimeTypeService, BundleListener {

    public static final String CORE_MIME_TYPES = "/META-INF/core_mime.types";

    public static final String MIME_TYPES = "/META-INF/mime.types";
    
    @ObjectClassDefinition(name = "Apache Sling Commons MIME Type Service",
            description = "The Sling Commons MIME Type Service provides support for " +
                "maintaining and configuring MIME Type mappings.")
    public @interface Config {

        @AttributeDefinition(name = "MIME Types",
                description = "Configures additional MIME type mappings in the "+
                 "traditional mime.types file format: Each property is a blank space separated "+
                 "list of strings where the first string is the MIME type and the rest of the "+
                 "strings are filename extensions referring to the MIME type. Using this "+
                 "property additional MIME type mappings may be defined. Existing MIME type "+
                 "mappings cannot be redefined and setting such mappings in this property "+
                 "has no effect. For a list of existing mappings refer to the MIME Types page.")
        String[] mime_types();
    }

    private Logger log = LoggerFactory.getLogger(this.getClass());
    
    private Map<String, String> mimeMap = new HashMap<>();

    private Map<String, String> extensionMap = new HashMap<>();

    private MimeTypeProvider[] typeProviders;

    private List<MimeTypeProvider> typeProviderList = new ArrayList<>();

    // --------- MimeTypeService interface

    @Override
    public String getMimeType(String name) {
        if (name == null) {
            return null;
        }

        String ext = name.substring(name.lastIndexOf('.') + 1);
        ext = ext.toLowerCase();

        String type = this.mimeMap.get(ext);
        if (type == null) {
            MimeTypeProvider[] mtp = this.getMimeTypeProviders();
            for (int i = 0; type == null && i < mtp.length; i++) {
                type = mtp[i].getMimeType(ext);
            }
        }

        return type;
    }

    @Override
    public String getExtension(String mimeType) {
        if (mimeType == null) {
            return null;
        }

        // compare using lowercase only
        mimeType = mimeType.toLowerCase();

        String ext = this.extensionMap.get(mimeType);
        if (ext == null) {
            MimeTypeProvider[] mtp = this.getMimeTypeProviders();
            for (int i = 0; ext == null && i < mtp.length; i++) {
                ext = mtp[i].getExtension(mimeType);
            }
        }
        return ext;
    }

    @Override
    public void registerMimeType(String mimeType, String... extensions) {
        if (mimeType == null || mimeType.length() == 0 || extensions == null
            || extensions.length == 0) {
            return;
        }

        mimeType = mimeType.toLowerCase();

        String defaultExtension = extensionMap.get(mimeType);

        for (String extension : extensions) {
            if (extension != null && extension.length() > 0) {
                extension = extension.toLowerCase();

                String oldMimeType = mimeMap.get(extension);
                if (oldMimeType == null) {

                    log.debug("registerMimeType: Add mapping "
                        + extension + "=" + mimeType);

                    this.mimeMap.put(extension, mimeType);

                    if (defaultExtension == null) {
                        defaultExtension = extension;
                    }

                } else {

                    log.info(
                        "registerMimeType: Ignoring mapping " + extension + "="
                            + mimeType + ": Mapping " + extension + "="
                            + oldMimeType + " already exists");

                }

            }
        }

        if (defaultExtension != null) {
            this.extensionMap.put(mimeType, defaultExtension);
        }
    }

    @Override
    public void registerMimeType(InputStream mimeTabStream) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(
            mimeTabStream, "ISO-8859-1"));

        String line;
        while ((line = br.readLine()) != null) {

            // ignore comment lines
            if (line.startsWith("#")) {
                continue;
            }

            registerMimeType(line);
        }
    }

    // ---------- SCR implementation -------------------------------------------

    @Activate
    protected void activate(final BundleContext context, final Config config) {
        context.addBundleListener(this);

        // register core and default sling mime types
        Bundle bundle = context.getBundle();
        registerMimeType(bundle.getEntry(CORE_MIME_TYPES));
        registerMimeType(bundle.getEntry(MIME_TYPES));

        // register maps of existing bundles
        Bundle[] bundles = context.getBundles();
        for (int i = 0; i < bundles.length; i++) {
            if ((bundles[i].getState() & (Bundle.RESOLVED | Bundle.STARTING
                | Bundle.ACTIVE | Bundle.STOPPING)) != 0
                && bundles[i].getBundleId() != bundle.getBundleId()) {
                this.registerMimeType(bundles[i].getEntry(MIME_TYPES));
            }
        }

        // register configuration properties
        if (config.mime_types() != null) {
            for (final String configType : config.mime_types()) {
                registerMimeType(configType);
            }
        }
    }

    @Deactivate
    protected void deactivate(final BundleContext context) {
        context.removeBundleListener(this);
    }

    @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
    protected void bindMimeTypeProvider(MimeTypeProvider mimeTypeProvider) {
        synchronized (this.typeProviderList) {
            this.typeProviderList.add(mimeTypeProvider);
            this.typeProviders = null;
        }
    }

    protected void unbindMimeTypeProvider(MimeTypeProvider mimeTypeProvider) {
        synchronized (this.typeProviderList) {
            this.typeProviderList.remove(mimeTypeProvider);
            this.typeProviders = null;
        }
    }

    // ---------- BundleListener ----------------------------------------------

    @Override
    public void bundleChanged(BundleEvent event) {
        if (event.getType() == BundleEvent.RESOLVED) {
            try {
                this.registerMimeType(event.getBundle().getEntry(MIME_TYPES));
            } catch (IllegalStateException ie) {
                log.info("bundleChanged: an issue while registering the mime type occurred");
            }
        }
    }

    // ---------- plugin support -----------------------------------------------

    public Map<String, String> getMimeMap() {
        return mimeMap;
    }

    public Map<String, String> getExtensionMap() {
        return extensionMap;
    }

    // ---------- internal -----------------------------------------------------

    private MimeTypeProvider[] getMimeTypeProviders() {
        MimeTypeProvider[] list = this.typeProviders;

        if (list == null) {
            synchronized (this.typeProviderList) {
                this.typeProviders = this.typeProviderList.toArray(new MimeTypeProvider[this.typeProviderList.size()]);
                list = this.typeProviders;
            }
        }

        return list;
    }

    private void registerMimeType(URL mimetypes) {
        if (mimetypes != null) {
            InputStream ins = null;
            try {
                ins = mimetypes.openStream();
                this.registerMimeType(ins);
            } catch (IOException ioe) {
                // log but don't actually care
                log.warn("An error occurred reading "
                    + mimetypes, ioe);
            } finally {
                if (ins != null) {
                    try {
                        ins.close();
                    } catch (IOException ioe) {
                        // ignore
                    }
                }
            }
        }
    }

    /**
     * Splits the <code>line</code> on whitespace an registers the MIME type
     * mappings provided the line contains more than one whitespace separated
     * fields.
     *
     * @throws NullPointerException if <code>line</code> is <code>null</code>.
     */
    private void registerMimeType(String line) {
        String[] parts = line.split("\\s+");
        if (parts.length > 1) {
            String[] extensions = new String[parts.length - 1];
            System.arraycopy(parts, 1, extensions, 0, extensions.length);
            this.registerMimeType(parts[0], extensions);
        }
    }

}
