/*
 * 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.javax.activation.internal;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.activation.CommandInfo;
import javax.activation.DataContentHandler;
import javax.activation.MailcapCommandMap;

import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sun.activation.registries.MailcapFile;

/**
 * The <tt>OsgiMailcapCommandMap</tt> is a <tt>CommandMap</tt> which ensures that {@link DataContentHandler} classes are
 * loaded by their containing bundles.
 *
 * <p>
 * This allows the javax.activation bundle to obey classloading contraints in an OSGi environment, while preserving most
 * of the functionality available in an unmodified version of the bundle. Notably, this implementation does not support
 * loading <tt>mailcap</tt> files which are not placed inside a bundle.
 * </p>
 */
public class OsgiMailcapCommandMap extends MailcapCommandMap {

    private static final Logger log = LoggerFactory.getLogger(OsgiMailcapCommandMap.class);

    private final Map<Bundle, MailcapFile> db = new HashMap<Bundle, MailcapFile>();
    private final Object sync = new Object();
    private Caller caller = null;

    @Override
    public synchronized void addMailcap(String mailcap) {
        if (caller == null) {
            caller = new Caller();
        }
        Bundle bundle = caller.get();
        if (bundle != null) {
            db.computeIfAbsent(bundle, x -> new MailcapFile())
                    .appendToMailcap(mailcap);
        }
    }

    public void addMailcapEntries(InputStream mailcapFile, Bundle originatingBundle) throws IOException {

        synchronized (sync) {
            db.put(originatingBundle, new MailcapFile(mailcapFile));
        }

        log.debug("Added mailcap entries from bundle {}", originatingBundle);
    }

    public void removeMailcapEntriesForBundle(Bundle bundle) {

        boolean removed;
        synchronized (sync) {
            removed = db.remove(bundle) != null;
        }

        if (removed) {
            log.debug("Removed mailcap entries from bundle {}", bundle);
        }
    }

    @Override
    public synchronized CommandInfo[] getPreferredCommands(String mimeType) {

        List<CommandInfo> commands = new ArrayList<CommandInfo>();

        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        getPreferredCommands(mimeType, commands, false);
        getPreferredCommands(mimeType, commands, true);

        return commands.toArray(new CommandInfo[commands.size()]);
    }

    private void getPreferredCommands(String mimeType, List<CommandInfo> accumulator, boolean fallback) {

        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            Map<?, ?> commandMap = fallback ? entry.getValue().getMailcapFallbackList(mimeType) : entry.getValue()
                    .getMailcapList(mimeType);

            if (commandMap == null) {
                continue;
            }

            for (Object verbObject : commandMap.keySet()) {
                String verb = (String) verbObject;

                if (!commandsHaveVerb(accumulator, verb)) {
                    List<?> commands = (List<?>) commandMap.get(verb);
                    String className = (String) commands.get(0);
                    accumulator.add(new CommandInfo(verb, className));
                }
            }
        }
    }

    @Override
    public synchronized CommandInfo[] getAllCommands(String mimeType) {
        List<CommandInfo> commands = new ArrayList<CommandInfo>();
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        getAllCommands(mimeType, commands, false);
        getAllCommands(mimeType, commands, true);

        return commands.toArray(new CommandInfo[commands.size()]);
    }

    private void getAllCommands(String mimeType, List<CommandInfo> accumulator, boolean fallback) {
        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            Map<?, ?> commandMap = fallback ? entry.getValue().getMailcapFallbackList(mimeType) :
                    entry.getValue().getMailcapList(mimeType);

            if (commandMap == null) {
                continue;
            }

            for (Object verbAsObject : commandMap.keySet()) {
                String verb = (String) verbAsObject;

                List<?> commands = (List<?>) commandMap.get(verb);

                for (Object command : commands) {
                    accumulator.add(new CommandInfo(verb, (String) command));
                }

            }
        }
    }

    @Override
    public synchronized CommandInfo getCommand(String mimeType, String cmdName) {
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        CommandInfo command = null;

        command = getCommand(mimeType, cmdName, false);
        if (command != null) {
            return command;
        }

        command = getCommand(mimeType, cmdName, true);

        return command;
    }

    private CommandInfo getCommand(String mimeType, String commandName, boolean fallback) {

        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            Map<?, ?> commandMap = fallback ? entry.getValue().getMailcapFallbackList(mimeType)
                    : entry.getValue().getMailcapList(mimeType);
            if (commandMap != null) {
                List<?> commands = (List<?>) commandMap.get(commandName);
                if (commands == null) {
                    continue;
                }

                String cmdClassName = (String) commands.get(0);

                if (cmdClassName != null) {
                    return new CommandInfo(commandName, cmdClassName);
                }
            }
        }

        return null;
    }

    @Override
    public synchronized DataContentHandler createDataContentHandler(String mimeType) {
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        DataContentHandler dch = findDataContentHandler(mimeType, false);

        if (dch != null) {
            return dch;
        }

        return findDataContentHandler(mimeType, true);
    }

    private DataContentHandler findDataContentHandler(String mimeType, boolean fallback) {

        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            Map<?, ?> commandMap = fallback ? entry.getValue().getMailcapFallbackList(mimeType) : entry.getValue()
                    .getMailcapList(mimeType);
            if (commandMap != null) {
                List<?> v = (List<?>) commandMap.get("content-handler");
                if (v == null) {
                    continue;
                }

                String name = (String) v.get(0);
                DataContentHandler dch = getDataContentHandler(name, entry.getKey());
                if (dch != null) {
                    return dch;
                }
            }
        }

        return null;
    }

    @Override
    public synchronized String[] getMimeTypes() {
        List<String> mimeTypesList = new ArrayList<String>();

        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            String[] mimeTypes = entry.getValue().getMimeTypes();
            for (String mimeType : mimeTypes) {
                if (!mimeTypesList.contains(mimeType)) {
                    mimeTypesList.add(mimeType);
                }
            }
        }

        return mimeTypesList.toArray(new String[mimeTypesList.size()]);
    }

    @Override
    public synchronized String[] getNativeCommands(String mimeType) {
        List<String> cmdList = new ArrayList<>();
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        for (Map.Entry<Bundle, MailcapFile> entry : db.entrySet()) {
            String[] cmds = entry.getValue().getNativeCommands(mimeType);
            if (cmds != null) {
                for (String cmd : cmds) {
                    if (!cmdList.contains(cmd)) {
                        cmdList.add(cmd);
                    }
                }
            }
        }

        return cmdList.toArray(new String[cmdList.size()]);
    }

    private DataContentHandler getDataContentHandler(String name, Bundle bundle) {
        try {
            return (DataContentHandler) bundle.loadClass(name).newInstance();
        } catch (InstantiationException e) {
            log.warn("Unable to instantiate " + DataContentHandler.class.getSimpleName() + " class ' " + name
                    + " ' from bundle " + bundle, e);
        } catch (IllegalAccessException e) {
            log.warn("Unable to instantiate " + DataContentHandler.class.getSimpleName() + " class ' " + name
                    + " ' from bundle " + bundle, e);
        } catch (ClassNotFoundException e) {
            log.warn("Unable to instantiate " + DataContentHandler.class.getSimpleName() + " class ' " + name
                    + " ' from bundle " + bundle, e);
        }

        return null;
    }

    private boolean commandsHaveVerb(List<CommandInfo> commands, String verb) {

        for (CommandInfo commandInfo : commands) {
            if (commandInfo.getCommandName().equals(verb)) {
                return true;
            }
        }

        return false;
    }

    private static final class Caller extends SecurityManager {
        Bundle get() {
            Class[] stack = getClassContext();
            for (int i = 0; i < stack.length; i++) {
                Bundle bundle = FrameworkUtil.getBundle(stack[i]);
                if (bundle != null && !bundle.equals(FrameworkUtil.getBundle(getClass()))) {
                    return bundle;
                }
            }
            return null;
        }
    }
}
