/*
 * 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.CommandMap;
import javax.activation.DataContentHandler;

import org.osgi.framework.Bundle;
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 CommandMap {

    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();

    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 CommandInfo[] getPreferredCommands(String mimeType) {

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

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

        synchronized (sync) {
            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 CommandInfo[] getAllCommands(String mimeType) {
        List<CommandInfo> commands = new ArrayList<CommandInfo>();
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        synchronized (sync) {
            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 CommandInfo getCommand(String mimeType, String cmdName) {
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        CommandInfo command = null;

        synchronized (sync) {
            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 DataContentHandler createDataContentHandler(String mimeType) {
        if (mimeType != null) {
            mimeType = mimeType.toLowerCase(Locale.ENGLISH);
        }

        synchronized (sync) {
            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;
    }

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

        synchronized (sync) {
            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()]);
    }

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