/*
 * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.net.www;
import java.net.URL;
import java.io.*;
import java.util.StringTokenizer;

public class MimeEntry implements Cloneable {
    private String typeName;    // of the form: "type/subtype"
    private String tempFileNameTemplate;

    private int action;
    private String command;
    private String description;
    private String imageFileName;
    private String fileExtensions[];

    boolean starred;

    // Actions
    public static final int             UNKNOWN                 = 0;
    public static final int             LOAD_INTO_BROWSER       = 1;
    public static final int             SAVE_TO_FILE            = 2;
    public static final int             LAUNCH_APPLICATION      = 3;

    static final String[] actionKeywords = {
        "unknown",
        "browser",
        "save",
        "application",
    };

    /**
     * Construct an empty entry of the given type and subtype.
     */
    public MimeEntry(String type) {
        // Default action is UNKNOWN so clients can decide what the default
        // should be, typically save to file or ask user.
        this(type, UNKNOWN, null, null, null);
    }

    //
    // The next two constructors are used only by the deprecated
    // PlatformMimeTable classes or, in last case, is called by the public
    // constructor.  They are kept here anticipating putting support for
    // mailcap formatted config files back in (so BOTH the properties format
    // and the mailcap formats are supported).
    //
    MimeEntry(String type, String imageFileName, String extensionString) {
        typeName = type.toLowerCase();
        action = UNKNOWN;
        command = null;
        this.imageFileName = imageFileName;
        setExtensions(extensionString);
        starred = isStarred(typeName);
    }

    // For use with MimeTable::parseMailCap
    MimeEntry(String typeName, int action, String command,
              String tempFileNameTemplate) {
        this.typeName = typeName.toLowerCase();
        this.action = action;
        this.command = command;
        this.imageFileName = null;
        this.fileExtensions = null;

        this.tempFileNameTemplate = tempFileNameTemplate;
    }

    // This is the one called by the public constructor.
    MimeEntry(String typeName, int action, String command,
              String imageFileName, String fileExtensions[]) {

        this.typeName = typeName.toLowerCase();
        this.action = action;
        this.command = command;
        this.imageFileName = imageFileName;
        this.fileExtensions = fileExtensions;

        starred = isStarred(typeName);

    }

    public synchronized String getType() {
        return typeName;
    }

    public synchronized void setType(String type) {
        typeName = type.toLowerCase();
    }

    public synchronized int getAction() {
        return action;
    }

    public synchronized void setAction(int action, String command) {
        this.action = action;
        this.command = command;
    }

    public synchronized void setAction(int action) {
        this.action = action;
    }

    public synchronized String getLaunchString() {
        return command;
    }

    public synchronized void setCommand(String command) {
        this.command = command;
    }

    public synchronized String getDescription() {
        return (description != null ? description : typeName);
    }

    public synchronized void setDescription(String description) {
        this.description = description;
    }

    // ??? what to return for the image -- the file name or should this return
    // something more advanced like an image source or something?
    // returning the name has the least policy associated with it.
    // pro tempore, we'll use the name
    public String getImageFileName() {
        return imageFileName;
    }

    public synchronized void setImageFileName(String filename) {
        File file = new File(filename);
        if (file.getParent() == null) {
            imageFileName = System.getProperty(
                                     "java.net.ftp.imagepath."+filename);
        }
        else {
            imageFileName = filename;
        }

        if (filename.lastIndexOf('.') < 0) {
            imageFileName = imageFileName + ".gif";
        }
    }

    public String getTempFileTemplate() {
        return tempFileNameTemplate;
    }

    public synchronized String[] getExtensions() {
        return fileExtensions;
    }

    public synchronized String getExtensionsAsList() {
        String extensionsAsString = "";
        if (fileExtensions != null) {
            for (int i = 0; i < fileExtensions.length; i++) {
                extensionsAsString += fileExtensions[i];
                if (i < (fileExtensions.length - 1)) {
                    extensionsAsString += ",";
                }
            }
        }

        return extensionsAsString;
    }

    public synchronized void setExtensions(String extensionString) {
        StringTokenizer extTokens = new StringTokenizer(extensionString, ",");
        int numExts = extTokens.countTokens();
        String extensionStrings[] = new String[numExts];

        for (int i = 0; i < numExts; i++) {
            String ext = (String)extTokens.nextElement();
            extensionStrings[i] = ext.trim();
        }

        fileExtensions = extensionStrings;
    }

    private boolean isStarred(String typeName) {
        return (typeName != null)
            && (typeName.length() > 0)
            && (typeName.endsWith("/*"));
    }

    /**
     * Invoke the MIME type specific behavior for this MIME type.
     * Returned value can be one of several types:
     * <ol>
     * <li>A thread -- the caller can choose when to launch this thread.
     * <li>A string -- the string is loaded into the browser directly.
     * <li>An input stream -- the caller can read from this byte stream and
     *     will typically store the results in a file.
     * <li>A document (?) --
     * </ol>
     */
    public Object launch(java.net.URLConnection urlc, InputStream is, MimeTable mt) throws ApplicationLaunchException {
        switch (action) {
        case SAVE_TO_FILE:
            // REMIND: is this really the right thing to do?
            try {
                return is;
            } catch(Exception e) {
                // I18N
                return "Load to file failed:\n" + e;
            }

        case LOAD_INTO_BROWSER:
            // REMIND: invoke the content handler?
            // may be the right thing to do, may not be -- short term
            // where docs are not loaded asynch, loading and returning
            // the content is the right thing to do.
            try {
                return urlc.getContent();
            } catch (Exception e) {
                return null;
            }

        case LAUNCH_APPLICATION:
            {
                String threadName = command;
                int fst = threadName.indexOf(' ');
                if (fst > 0) {
                    threadName = threadName.substring(0, fst);
                }

                return new MimeLauncher(this, urlc, is,
                                        mt.getTempFileTemplate(), threadName);
            }

        case UNKNOWN:
            // REMIND: What do do here?
            return null;
        }

        return null;
    }

    public boolean matches(String type) {
        if (starred) {
          // REMIND: is this the right thing or not?
          return type.startsWith(typeName);
        } else {
            return type.equals(typeName);
        }
    }

    public Object clone() {
        // return a shallow copy of this.
        MimeEntry theClone = new MimeEntry(typeName);
        theClone.action = action;
        theClone.command = command;
        theClone.description = description;
        theClone.imageFileName = imageFileName;
        theClone.tempFileNameTemplate = tempFileNameTemplate;
        theClone.fileExtensions = fileExtensions;

        return theClone;
    }

    public synchronized String toProperty() {
        StringBuffer buf = new StringBuffer();

        String separator = "; ";
        boolean needSeparator = false;

        int action = getAction();
        if (action != MimeEntry.UNKNOWN) {
            buf.append("action=" + actionKeywords[action]);
            needSeparator = true;
        }

        String command = getLaunchString();
        if (command != null && command.length() > 0) {
            if (needSeparator) {
                buf.append(separator);
            }
            buf.append("application=" + command);
            needSeparator = true;
        }

        if (getImageFileName() != null) {
            if (needSeparator) {
                buf.append(separator);
            }
            buf.append("icon=" + getImageFileName());
            needSeparator = true;
        }

        String extensions = getExtensionsAsList();
        if (extensions.length() > 0) {
            if (needSeparator) {
                buf.append(separator);
            }
            buf.append("file_extensions=" + extensions);
            needSeparator = true;
        }

        String description = getDescription();
        if (description != null && !description.equals(getType())) {
            if (needSeparator) {
                buf.append(separator);
            }
            buf.append("description=" + description);
        }

        return buf.toString();
    }

    public String toString() {
        return "MimeEntry[contentType=" + typeName
            + ", image=" + imageFileName
            + ", action=" + action
            + ", command=" + command
            + ", extensions=" + getExtensionsAsList()
            + "]";
    }
}
