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

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.security.Security;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @version $Rev$ $Date$
 */
public class MailcapCommandMap extends CommandMap {
    private final Map mimeTypes = new HashMap();
    private final Map preferredCommands = new HashMap();
    private final Map allCommands = new HashMap();
    // the unparsed commands from the mailcap file.
    private final Map nativeCommands = new HashMap();
    // commands identified as fallbacks...these are used last, and also used as wildcards.
    private final Map fallbackCommands = new HashMap();
    private URL url;

    public MailcapCommandMap() {
        ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
        // process /META-INF/mailcap.default
        try {
            InputStream is = MailcapCommandMap.class.getResourceAsStream("/META-INF/mailcap.default");
            if (is != null) {
                try {
                    parseMailcap(is);
                } finally {
                    is.close();
                }
            }
        } catch (IOException e) {
            // ignore
        }

        // process /META-INF/mailcap resources
        try {
            Enumeration e = contextLoader.getResources("META-INF/mailcap");
            while (e.hasMoreElements()) {
                url = ((URL) e.nextElement());
                try {
                    InputStream is = url.openStream();
                    try {
                        parseMailcap(is);
                    } finally {
                        is.close();
                    }
                } catch (IOException e1) {
                    continue;
                }
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        // process ${java.home}/lib/mailcap
        try {
            File file = new File(System.getProperty("java.home"), "lib/mailcap");
            InputStream is = new FileInputStream(file);
            try {
                parseMailcap(is);
            } finally {
                is.close();
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }

        // process ${user.home}/lib/mailcap
        try {
            File file = new File(System.getProperty("user.home"), ".mailcap");
            InputStream is = new FileInputStream(file);
            try {
                parseMailcap(is);
            } finally {
                is.close();
            }
        } catch (SecurityException e) {
            // ignore
        } catch (IOException e) {
            // ignore
        }
    }

    public MailcapCommandMap(String fileName) throws IOException {
        this();
        FileReader reader = new FileReader(fileName);
        try {
            parseMailcap(reader);
        } finally {
            reader.close();
        }
    }

    public MailcapCommandMap(InputStream is) {
        this();
        parseMailcap(is);
    }

    private void parseMailcap(InputStream is) {
        try {
            parseMailcap(new InputStreamReader(is));
        } catch (IOException e) {
            // spec API means all we can do is swallow this
        }
    }

    void parseMailcap(Reader reader) throws IOException {
        BufferedReader br = new BufferedReader(reader);
        String line;
        while ((line = br.readLine()) != null) {
            addMailcap(line);
        }
    }

    public synchronized void addMailcap(String mail_cap) {
        int index = 0;
        // skip leading whitespace
        index = skipSpace(mail_cap, index);
        if (index == mail_cap.length() || mail_cap.charAt(index) == '#') {
            return;
        }

        // get primary type
        int start = index;
        index = getToken(mail_cap, index);
        if (start == index) {
            return;
        }
        String mimeType = mail_cap.substring(start, index);

        // skip any spaces after the primary type
        index = skipSpace(mail_cap, index);
        if (index == mail_cap.length() || mail_cap.charAt(index) == '#') {
            return;
        }

        // get sub-type
        if (mail_cap.charAt(index) == '/') {
            index = skipSpace(mail_cap, ++index);
            start = index;
            index = getToken(mail_cap, index);
            mimeType = mimeType + '/' + mail_cap.substring(start, index);
        } else {

            mimeType = mimeType + "/*";
        }

        // we record all mappings using the lowercase version.
        mimeType = mimeType.toLowerCase();

        // skip spaces after mime type
        index = skipSpace(mail_cap, index);

        // expect a ';' to terminate field 1
        if (index == mail_cap.length() || mail_cap.charAt(index) != ';') {
            return;
        }
        // ok, we've parsed the mime text field, now parse the view field.  If there's something
        // there, then we add this to the native text.
        index = skipSpace(mail_cap, index + 1);
        // if the next encountered text is not a ";", then we have a view.  This gets added to the
        // native list.
        if (index == mail_cap.length() || mail_cap.charAt(index) != ';') {
            ArrayList nativeCommandList = (ArrayList)nativeCommands.get(mimeType);

            // if this is the first for this mimetype, create a holder
            if (nativeCommandList == null) {
                nativeCommandList = new ArrayList();
                nativeCommands.put(mimeType, nativeCommandList);
            }

            // now add this as an entry in the list.
            nativeCommandList.add(mail_cap);
            // now skip forward to the next field marker, if any
            index = getMText(mail_cap, index);
        }

        // we don't know which list this will be added to until we finish parsing, as there
        // can be an x-java-fallback-entry parameter that moves this to the fallback list.
        List commandList = new ArrayList();
        // but by default, this is not a fallback.
        boolean fallback = false;

        int fieldNumber = 0;

        // parse fields
        while (index < mail_cap.length() && mail_cap.charAt(index) == ';') {
            index = skipSpace(mail_cap, index + 1);
            start = index;
            index = getToken(mail_cap, index);
            String fieldName = mail_cap.substring(start, index).toLowerCase();
            index = skipSpace(mail_cap, index);
            if (index < mail_cap.length() && mail_cap.charAt(index) == '=') {
                index = skipSpace(mail_cap, index + 1);
                start = index;
                index = getMText(mail_cap, index);
                String value = mail_cap.substring(start, index);
                index = skipSpace(mail_cap, index);
                if (fieldName.startsWith("x-java-") && fieldName.length() > 7) {
                    String command = fieldName.substring(7);
                    value = value.trim();
                    if (command.equals("fallback-entry")) {
                        if (value.equals("true")) {
                            fallback = true;
                        }
                    }
                    else {
                        // create a CommandInfo item and add it the accumulator
                        CommandInfo info = new CommandInfo(command, value);
                        commandList.add(info);
                    }
                }
            }
        }
        addCommands(mimeType, commandList, fallback);
    }

    /**
     * Add a parsed list of commands to the appropriate command list.
     *
     * @param mimeType The mimeType name this is added under.
     * @param commands A List containing the command information.
     * @param fallback The target list identifier.
     */
    protected void addCommands(String mimeType, List commands, boolean fallback) {
        // add this to the mimeType set
        mimeTypes.put(mimeType, mimeType);
        // the target list changes based on the type of entry.
        Map target = fallback ? fallbackCommands : preferredCommands;

        // now process
        for (Iterator i = commands.iterator(); i.hasNext();) {
            CommandInfo info = (CommandInfo)i.next();
            addCommand(target, mimeType, info);
            // if this is not a fallback position, then this to the allcommands list.
            if (!fallback) {
                List cmdList = (List) allCommands.get(mimeType);
                if (cmdList == null) {
                    cmdList = new ArrayList();
                    allCommands.put(mimeType, cmdList);
                }
                cmdList.add(info);
            }
        }
    }


    /**
     * Add a command to a target command list (preferred or fallback).
     *
     * @param commandList
     *                 The target command list.
     * @param mimeType The MIME type the command is associated with.
     * @param command  The command information.
     */
    protected void addCommand(Map commandList, String mimeType, CommandInfo command) {

        Map commands = (Map) commandList.get(mimeType);
        if (commands == null) {
            commands = new HashMap();
            commandList.put(mimeType, commands);
        }
        commands.put(command.getCommandName(), command);
    }


    private int skipSpace(String s, int index) {
        while (index < s.length() && Character.isWhitespace(s.charAt(index))) {
            index++;
        }
        return index;
    }

    private int getToken(String s, int index) {
        while (index < s.length() && s.charAt(index) != '#' && !MimeType.isSpecial(s.charAt(index))) {
            index++;
        }
        return index;
    }

    private int getMText(String s, int index) {
        while (index < s.length()) {
            char c = s.charAt(index);
            if (c == '#' || c == ';' || Character.isISOControl(c)) {
                return index;
            }
            if (c == '\\') {
                index++;
                if (index == s.length()) {
                    return index;
                }
            }
            index++;
        }
        return index;
    }

    public synchronized CommandInfo[] getPreferredCommands(String mimeType) {
        // get the mimetype as a lowercase version.
        mimeType = mimeType.toLowerCase();

        Map commands = (Map) preferredCommands.get(mimeType);
        if (commands == null) {
            commands = (Map) preferredCommands.get(getWildcardMimeType(mimeType));
        }

        Map fallbackCommands = getFallbackCommands(mimeType);

        // if we have fall backs, then we need to merge this stuff.
        if (fallbackCommands != null) {
            // if there's no command list, we can just use this as the master list.
            if (commands == null) {
                commands = fallbackCommands;
            }
            else {
                // merge the two lists.  The ones in the commands list will take precedence.
                commands = mergeCommandMaps(commands, fallbackCommands);
            }
        }

        // now convert this into an array result.
        if (commands == null) {
            return new CommandInfo[0];
        }
        return (CommandInfo[]) commands.values().toArray(new CommandInfo[commands.size()]);
    }

    private Map getFallbackCommands(String mimeType) {
        Map commands = (Map) fallbackCommands.get(mimeType);

        // now we also need to search this as if it was a wildcard.  If we get a wildcard hit,
        // we have to merge the two lists.
        Map wildcardCommands = (Map)fallbackCommands.get(getWildcardMimeType(mimeType));
        // no wildcard version
        if (wildcardCommands == null) {
            return commands;
        }
        // we need to merge these.
        return mergeCommandMaps(commands, wildcardCommands);
    }


    private Map mergeCommandMaps(Map main, Map fallback) {
        // create a cloned copy of the second map.  We're going to use a PutAll operation to
        // overwrite any duplicates.
        Map result = new HashMap(fallback);
        result.putAll(main);

        return result;
    }

    public synchronized CommandInfo[] getAllCommands(String mimeType) {
        mimeType = mimeType.toLowerCase();
        List exactCommands = (List) allCommands.get(mimeType);
        if (exactCommands == null) {
            exactCommands = Collections.EMPTY_LIST;
        }
        List wildCommands = (List) allCommands.get(getWildcardMimeType(mimeType));
        if (wildCommands == null) {
            wildCommands = Collections.EMPTY_LIST;
        }

        Map fallbackCommands = getFallbackCommands(mimeType);
        if (fallbackCommands == null) {
            fallbackCommands = Collections.EMPTY_MAP;
        }


        CommandInfo[] result = new CommandInfo[exactCommands.size() + wildCommands.size() + fallbackCommands.size()];
        int j = 0;
        for (int i = 0; i < exactCommands.size(); i++) {
            result[j++] = (CommandInfo) exactCommands.get(i);
        }
        for (int i = 0; i < wildCommands.size(); i++) {
            result[j++] = (CommandInfo) wildCommands.get(i);
        }

        for (Iterator i = fallbackCommands.keySet().iterator(); i.hasNext();) {
            result[j++] = (CommandInfo) fallbackCommands.get((String)i.next());
        }
        return result;
    }

    public synchronized CommandInfo getCommand(String mimeType, String cmdName) {
        mimeType = mimeType.toLowerCase();
        // strip any parameters from the supplied mimeType
        int i = mimeType.indexOf(';');
        if (i != -1) {
            mimeType = mimeType.substring(0, i).trim();
        }
        cmdName = cmdName.toLowerCase();

        // search for an exact match
        Map commands = (Map) preferredCommands.get(mimeType);
        if (commands == null || commands.get(cmdName) == null) {
            // then a wild card match
            commands = (Map) preferredCommands.get(getWildcardMimeType(mimeType));
            if (commands == null || commands.get(cmdName) == null) {
                // then fallback searches, both standard and wild card.
                commands = (Map) fallbackCommands.get(mimeType);
                if (commands == null || commands.get(cmdName) == null) {
                    commands = (Map) fallbackCommands.get(getWildcardMimeType(mimeType));
                }
                if (commands == null) {
                    return null;
                }
            }
        }
        return (CommandInfo) commands.get(cmdName);
    }

    private String getWildcardMimeType(String mimeType) {
        int i = mimeType.indexOf('/');
        if (i == -1) {
            return mimeType + "/*";
        } else {
            return mimeType.substring(0, i + 1) + "*";
        }
    }

    public synchronized DataContentHandler createDataContentHandler(String mimeType) {

        CommandInfo info = getCommand(mimeType, "content-handler");
        if (info == null) {
            return null;
        }

        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        if (cl == null) {
            cl = getClass().getClassLoader();
        }
        try {
            return (DataContentHandler) cl.loadClass(info.getCommandClass()).newInstance();
        } catch (ClassNotFoundException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        } catch (InstantiationException e) {
            return null;
        }
    }

    /**
     * Get all MIME types known to this command map.
     *
     * @return A String array of the MIME type names.
     */
    public synchronized String[] getMimeTypes() {
        ArrayList types = new ArrayList(mimeTypes.values());
        return (String[])types.toArray(new String[types.size()]);
    }

    /**
     * Return the list of raw command strings parsed
     * from the mailcap files for a given mimeType.
     *
     * @param mimeType The target mime type
     *
     * @return A String array of the raw command strings.  Returns
     *         an empty array if the mimetype is not currently known.
     */
    public synchronized String[] getNativeCommands(String mimeType) {
        ArrayList commands = (ArrayList)nativeCommands.get(mimeType.toLowerCase());
        if (commands == null) {
            return new String[0];
        }
        return (String[])commands.toArray(new String[commands.size()]);
    }
}
