/*
 * Copyright (c) 2011, 2012, 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 com.apple.eawt;

import java.awt.*;
import java.awt.peer.*;
import java.beans.Beans;

import javax.swing.JMenuBar;

import sun.lwawt.*;
import sun.lwawt.macosx.*;

/**
 * The <code>Application</code> class allows you to integrate your Java application with the native Mac OS X environment.
 * You can provide your Mac OS X users a greatly enhanced experience by implementing a few basic handlers for standard system events.
 *
 * For example:
 * <ul>
 * <li>Open an about dialog when a user chooses About from the application menu.</li>
 * <li>Open a preferences window when the users chooses Preferences from the application menu.</li>
 * <li>Create a new document when the user clicks on your Dock icon, and no windows are open.</li>
 * <li>Open a document that the user double-clicked on in the Finder.</li>
 * <li>Open a custom URL scheme when a user clicks on link in a web browser.</li>
 * <li>Reconnect to network services after the system has awoke from sleep.</li>
 * <li>Cleanly shutdown your application when the user chooses Quit from the application menu, Dock icon, or types Command-Q.</li>
 * <li>Cancel shutdown/logout if the user has unsaved changes in your application.</li>
 * </ul>
 *
 * @since 1.4
 */
public class Application {
    private static native void nativeInitializeApplicationDelegate();

    static Application sApplication = null;

    static {
        java.security.AccessController.doPrivileged(
            new java.security.PrivilegedAction<Void>() {
                public Void run() {
                    System.loadLibrary("awt");
                    return null;
                }
            });

        checkSecurity();
        if (!Beans.isDesignTime()) {
            nativeInitializeApplicationDelegate();
        }

        sApplication = new Application();
    }

    private static void checkSecurity() {
        final SecurityManager security = System.getSecurityManager();
        if (security == null) return;
        security.checkPermission(new RuntimePermission("canProcessApplicationEvents"));
    }

    /**
     * @return the singleton representing this Mac OS X Application
     *
     * @since 1.4
     */
    public static Application getApplication() {
        checkSecurity();
        return sApplication;
    }

    // some singletons, since they get called back into from native
    final _AppEventHandler eventHandler = _AppEventHandler.getInstance();
    final _AppMenuBarHandler menuBarHandler = _AppMenuBarHandler.getInstance();
    final _AppDockIconHandler iconHandler = new _AppDockIconHandler();

    /**
     * Creates an Application instance. Should only be used in JavaBean environments.
     * @deprecated use {@link #getApplication()}
     *
     * @since 1.4
     */
    @Deprecated
    public Application() {
        checkSecurity();
    }

    /**
     * Adds sub-types of {@link AppEventListener} to listen for notifications from the native Mac OS X system.
     *
     * @see AppForegroundListener
     * @see AppHiddenListener
     * @see AppReOpenedListener
     * @see ScreenSleepListener
     * @see SystemSleepListener
     * @see UserSessionListener
     *
     * @param listener
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void addAppEventListener(final AppEventListener listener) {
        eventHandler.addListener(listener);
    }

    /**
     * Removes sub-types of {@link AppEventListener} from listening for notifications from the native Mac OS X system.
     *
     * @see AppForegroundListener
     * @see AppHiddenListener
     * @see AppReOpenedListener
     * @see ScreenSleepListener
     * @see SystemSleepListener
     * @see UserSessionListener
     *
     * @param listener
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void removeAppEventListener(final AppEventListener listener) {
        eventHandler.removeListener(listener);
    }

    /**
     * Installs a handler to show a custom About window for your application.
     *
     * Setting the {@link AboutHandler} to <code>null</code> reverts it to the default Cocoa About window.
     *
     * @param aboutHandler the handler to respond to the {@link AboutHandler#handleAbout()} message
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setAboutHandler(final AboutHandler aboutHandler) {
        eventHandler.aboutDispatcher.setHandler(aboutHandler);
    }

    /**
     * Installs a handler to create the Preferences menu item in your application's app menu.
     *
     * Setting the {@link PreferencesHandler} to <code>null</code> will remove the Preferences item from the app menu.
     *
     * @param preferencesHandler
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setPreferencesHandler(final PreferencesHandler preferencesHandler) {
        eventHandler.preferencesDispatcher.setHandler(preferencesHandler);
    }

    /**
     * Installs the handler which is notified when the application is asked to open a list of files.
     * The {@link OpenFilesHandler#openFiles(AppEvent.OpenFilesEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleDocumentTypes</code> array present in it's Info.plist.
     * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleDocumentTypes</code> key to your app's Info.plist.
     *
     * @param openFileHandler
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setOpenFileHandler(final OpenFilesHandler openFileHandler) {
        eventHandler.openFilesDispatcher.setHandler(openFileHandler);
    }

    /**
     * Installs the handler which is notified when the application is asked to print a list of files.
     * The {@link PrintFilesHandler#printFiles(AppEvent.PrintFilesEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleDocumentTypes</code> array present in it's Info.plist.
     * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleDocumentTypes</code> key to your app's Info.plist.
     *
     * @param printFileHandler
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setPrintFileHandler(final PrintFilesHandler printFileHandler) {
        eventHandler.printFilesDispatcher.setHandler(printFileHandler);
    }

    /**
     * Installs the handler which is notified when the application is asked to open a URL.
     * The {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} notifications are only sent if the Java app is a bundled application, with a <code>CFBundleURLTypes</code> array present in it's Info.plist.
     * See the <a href="http://developer.apple.com/mac/library/documentation/General/Reference/InfoPlistKeyReference">Info.plist Key Reference</a> for more information about adding a <code>CFBundleURLTypes</code> key to your app's Info.plist.
     *
     * Setting the handler to <code>null</code> causes all {@link OpenURIHandler#openURI(AppEvent.OpenURIEvent)} requests to be enqueued until another handler is set.
     *
     * @param openURIHandler
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setOpenURIHandler(final OpenURIHandler openURIHandler) {
        eventHandler.openURIDispatcher.setHandler(openURIHandler);
    }

    /**
     * Installs the handler which determines if the application should quit.
     * The handler is passed a one-shot {@link QuitResponse} which can cancel or proceed with the quit.
     * Setting the handler to <code>null</code> causes all quit requests to directly perform the default {@link QuitStrategy}.
     *
     * @param quitHandler the handler that is called when the application is asked to quit
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setQuitHandler(final QuitHandler quitHandler) {
        eventHandler.quitDispatcher.setHandler(quitHandler);
    }

    /**
     * Sets the default strategy used to quit this application. The default is calling SYSTEM_EXIT_0.
     *
     * The quit strategy can also be set with the "apple.eawt.quitStrategy" system property.
     *
     * @param strategy the way this application should be shutdown
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void setQuitStrategy(final QuitStrategy strategy) {
        eventHandler.setDefaultQuitStrategy(strategy);
    }

    /**
     * Enables this application to be suddenly terminated.
     *
     * Call this method to indicate your application's state is saved, and requires no notification to be terminated.
     * Letting your application remain terminatable improves the user experience by avoiding re-paging in your application when it's asked to quit.
     *
     * <b>Note: enabling sudden termination will allow your application to be quit without notifying your QuitHandler, or running any shutdown hooks.</b>
     * User initiated Cmd-Q, logout, restart, or shutdown requests will effectively "kill -KILL" your application.
     *
     * This call has no effect on Mac OS X versions prior to 10.6.
     *
     * @see <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSProcessInfo_Class">NSProcessInfo class references</a> for more information about Sudden Termination.
     * @see Application#disableSuddenTermination()
     *
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void enableSuddenTermination() {
        _AppMiscHandlers.enableSuddenTermination();
    }

    /**
     * Prevents this application from being suddenly terminated.
     *
     * Call this method to indicate that your application has unsaved state, and may not be terminated without notification.
     *
     * This call has no effect on Mac OS X versions prior to 10.6.
     *
     * @see <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/foundation/Classes/NSProcessInfo_Class">NSProcessInfo class references</a> for more information about Sudden Termination.
     * @see Application#enableSuddenTermination()
     *
     * @since Java for Mac OS X 10.6 Update 3
     * @since Java for Mac OS X 10.5 Update 8
     */
    public void disableSuddenTermination() {
        _AppMiscHandlers.disableSuddenTermination();
    }

    /**
     * Requests this application to move to the foreground.
     *
     * @param allWindows if all windows of this application should be moved to the foreground, or only the foremost one
     *
     * @since Java for Mac OS X 10.6 Update 1
     * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
     */
    public void requestForeground(final boolean allWindows) {
        _AppMiscHandlers.requestActivation(allWindows);
    }

    /**
     * Requests user attention to this application (usually through bouncing the Dock icon). Critical
     * requests will continue to bounce the Dock icon until the app is activated. An already active
     * application requesting attention does nothing.
     *
     * @param critical if this is an important request
     *
     * @since Java for Mac OS X 10.6 Update 1
     * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
     */
    public void requestUserAttention(final boolean critical) {
        _AppMiscHandlers.requestUserAttention(critical);
    }

    /**
     * Opens the native help viewer application if a Help Book has been added to the
     * application bundler and registered in the Info.plist with CFBundleHelpBookFolder.
     *
     * See http://developer.apple.com/qa/qa2001/qa1022.html for more information.
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public void openHelpViewer() {
        _AppMiscHandlers.openHelpViewer();
    }

    /**
     * Attaches the contents of the provided PopupMenu to the application's Dock icon.
     *
     * @param menu the PopupMenu to attach to this application's Dock icon
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public void setDockMenu(final PopupMenu menu) {
        iconHandler.setDockMenu(menu);
    }

    /**
     * @return the PopupMenu used to add items to this application's Dock icon
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public PopupMenu getDockMenu() {
        return iconHandler.getDockMenu();
    }

    /**
     * Changes this application's Dock icon to the provided image.
     *
     * @param image
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public void setDockIconImage(final Image image) {
        iconHandler.setDockIconImage(image);
    }

    /**
     * Obtains an image of this application's Dock icon.
     *
     * @return an image of this application's Dock icon
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public Image getDockIconImage() {
        return iconHandler.getDockIconImage();
    }

    /**
     * Affixes a small system provided badge to this application's Dock icon. Usually a number.
     *
     * @param badge textual label to affix to the Dock icon
     *
     * @since Java for Mac OS X 10.5 - 1.5
     * @since Java for Mac OS X 10.5 Update 1 - 1.6
     */
    public void setDockIconBadge(final String badge) {
        iconHandler.setDockIconBadge(badge);
    }

    /**
     * Sets the default menu bar to use when there are no active frames.
     * Only used when the system property "apple.laf.useScreenMenuBar" is "true", and
     * the Aqua Look and Feel is active.
     *
     * @param menuBar to use when no other frames are active
     *
     * @since Java for Mac OS X 10.6 Update 1
     * @since Java for Mac OS X 10.5 Update 6 - 1.6, 1.5
     */
    public void setDefaultMenuBar(final JMenuBar menuBar) {
        menuBarHandler.setDefaultMenuBar(menuBar);
    }

    /**
     * Requests that a {@link Window} should animate into or out of full screen mode.
     * Only {@link Window}s marked as full screenable by {@link FullScreenUtilities#setWindowCanFullScreen(Window, boolean)} can be toggled.
     *
     * @param window to animate into or out of full screen mode
     *
     * @since Java for Mac OS X 10.7 Update 1
     */
    @SuppressWarnings("deprecation")
    public void requestToggleFullScreen(final Window window) {
        final ComponentPeer peer = window.getPeer();

        if (!(peer instanceof LWWindowPeer)) return;
        Object platformWindow = ((LWWindowPeer) peer).getPlatformWindow();
        if (!(platformWindow instanceof CPlatformWindow)) return;
        ((CPlatformWindow)platformWindow).toggleFullScreen();
    }


    // -- DEPRECATED API --

    /**
     * Adds the specified ApplicationListener as a receiver of callbacks from this class.
     * This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
     *
     * @param listener an implementation of ApplicationListener that handles ApplicationEvents
     *
     * @deprecated register individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
     * @since 1.4
     */
    @SuppressWarnings("deprecation")
    @Deprecated
    public void addApplicationListener(final ApplicationListener listener) {
        eventHandler.legacyHandler.addLegacyAppListener(listener);
    }

    /**
     * Removes the specified ApplicationListener from being a receiver of callbacks from this class.
     * This method throws a RuntimeException if the newer About, Preferences, Quit, etc handlers are installed.
     *
     * @param listener an implementation of ApplicationListener that had previously been registered to handle ApplicationEvents
     *
     * @deprecated unregister individual handlers for each task (About, Preferences, Open, Print, Quit, etc)
     * @since 1.4
     */
    @SuppressWarnings("deprecation")
    @Deprecated
    public void removeApplicationListener(final ApplicationListener listener) {
        eventHandler.legacyHandler.removeLegacyAppListener(listener);
    }

    /**
     * Enables the Preferences item in the application menu. The ApplicationListener receives a callback for
     * selection of the Preferences item in the application menu only if this is set to <code>true</code>.
     *
     * If a Preferences item isn't present, this method adds and enables it.
     *
     * @param enable specifies whether the Preferences item in the application menu should be enabled (<code>true</code>) or not (<code>false</code>)
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public void setEnabledPreferencesMenu(final boolean enable) {
        menuBarHandler.setPreferencesMenuItemVisible(true);
        menuBarHandler.setPreferencesMenuItemEnabled(enable);
    }

    /**
     * Enables the About item in the application menu. The ApplicationListener receives a callback for
     * selection of the About item in the application menu only if this is set to <code>true</code>. Because AWT supplies
     * a standard About window when an application may not, by default this is set to <code>true</code>.
     *
     * If the About item isn't present, this method adds and enables it.
     *
     * @param enable specifies whether the About item in the application menu should be enabled (<code>true</code>) or not (<code>false</code>)
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public void setEnabledAboutMenu(final boolean enable) {
        menuBarHandler.setAboutMenuItemEnabled(enable);
    }

    /**
     * Determines if the Preferences item of the application menu is enabled.
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public boolean getEnabledPreferencesMenu() {
        return menuBarHandler.isPreferencesMenuItemEnabled();
    }

    /**
     * Determines if the About item of the application menu is enabled.
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public boolean getEnabledAboutMenu() {
        return menuBarHandler.isAboutMenuItemEnabled();
    }

    /**
     * Determines if the About item of the application menu is present.
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public boolean isAboutMenuItemPresent() {
        return menuBarHandler.isAboutMenuItemVisible();
    }

    /**
     * Adds the About item to the application menu if the item is not already present.
     *
     * @deprecated use {@link #setAboutHandler(AboutHandler)} with a non-null {@link AboutHandler} parameter
     * @since 1.4
     */
    @Deprecated
    public void addAboutMenuItem() {
        menuBarHandler.setAboutMenuItemVisible(true);
    }

    /**
     * Removes the About item from the application menu if  the item is present.
     *
     * @deprecated use {@link #setAboutHandler(AboutHandler)} with a null parameter
     * @since 1.4
     */
    @Deprecated
    public void removeAboutMenuItem() {
        menuBarHandler.setAboutMenuItemVisible(false);
    }

    /**
     * Determines if the About Preferences of the application menu is present. By default there is no Preferences menu item.
     *
     * @deprecated no replacement
     * @since 1.4
     */
    @Deprecated
    public boolean isPreferencesMenuItemPresent() {
        return menuBarHandler.isPreferencesMenuItemVisible();
    }

    /**
     * Adds the Preferences item to the application menu if the item is not already present.
     *
     * @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a non-null {@link PreferencesHandler} parameter
     * @since 1.4
     */
    @Deprecated
    public void addPreferencesMenuItem() {
        menuBarHandler.setPreferencesMenuItemVisible(true);
    }

    /**
     * Removes the Preferences item from the application menu if that item is present.
     *
     * @deprecated use {@link #setPreferencesHandler(PreferencesHandler)} with a null parameter
     * @since 1.4
     */
    @Deprecated
    public void removePreferencesMenuItem() {
        menuBarHandler.setPreferencesMenuItemVisible(false);
    }

    /**
     * @deprecated Use <code>java.awt.MouseInfo.getPointerInfo().getLocation()</code>.
     *
     * @since 1.4
     */
    @Deprecated
    public static Point getMouseLocationOnScreen() {
        return java.awt.MouseInfo.getPointerInfo().getLocation();
    }
}
