/*
 * Copyright (c) 2007-2010 by The Broad Institute, Inc. and the Massachusetts Institute of Technology.
 * All Rights Reserved.
 *
 * This software is licensed under the terms of the GNU Lesser General Public License (LGPL), Version 2.1 which
 * is available at http://www.opensource.org/licenses/lgpl-2.1.php.
 *
 * THE SOFTWARE IS PROVIDED "AS IS." THE BROAD AND MIT MAKE NO REPRESENTATIONS OR WARRANTIES OF
 * ANY KIND CONCERNING THE SOFTWARE, EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT
 * OR OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE.  IN NO EVENT SHALL THE BROAD OR MIT, OR THEIR
 * RESPECTIVE TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES, AND AFFILIATES BE LIABLE FOR ANY DAMAGES OF
 * ANY KIND, INCLUDING, WITHOUT LIMITATION, INCIDENTAL OR CONSEQUENTIAL DAMAGES, ECONOMIC
 * DAMAGES OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER THE BROAD OR MIT SHALL
 * BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF THE POSSIBILITY OF THE
 * FOREGOING.
 */
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.broad.igv.ui;

//~--- JDK imports ------------------------------------------------------------

import org.apache.log4j.Logger;
import org.broad.igv.Globals;
import org.broad.igv.exceptions.DataLoadException;
import org.broad.igv.track.TrackType;

import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.prefs.Preferences;

/**
 * @author jrobinso
 */
public class UIConstants {

    private static Logger log = Logger.getLogger(UIConstants.class);
    /**
     * Field description
     */
    final public static int groupGap = 10;
    final public static String APPLICATION_NAME = "IGV";
    final public static String APPLICATION_LONG_NAME = "Integrative Genomics Viewer";
    final public static boolean IS_WINDOWS =
            System.getProperty("os.name").toLowerCase().startsWith("windows");
    final public static boolean IS_MAC =
            System.getProperty("os.name").toLowerCase().startsWith("mac");
    final public static boolean IS_LINUX =
            System.getProperty("os.name").toLowerCase().startsWith("linux");
    final public static Dimension preferredSize = new Dimension(1000, 750);

    // To support mutation track overlay.  Generalize later.  Cancer specific option.
    public static TrackType overlayTrackType = TrackType.MUTATION;

    private static int doubleClickInterval = -1;
    // General
    final static public String CLICK_ITEM_TO_EDIT_TOOLTIP = "Click this item bring up its editor";
    final static public String LOAD_TRACKS_TOOLTIP = "Load data, features or sample information";
    final static public String LOAD_SERVER_DATA_TOOLTIP = "Load data, features or sample information from a server";
    final static public String SAVE_IMAGE_TOOLTIP = "Capture and save an image";
    final static public String NEW_SESSION_TOOLTIP = "Create a new session";
    final static public String SAVE_SESSION_TOOLTIP = "Save the current session";
    final static public String RESTORE_SESSION_TOOLTIP = "Reload the named session";
    final static public String EXIT_TOOLTIP = "Exit the application";
    final static public String EXPORT_REGION_TOOLTIP = "Allows currently selected regions to be exported to a file";
    final static public String IMPORT_REGION_TOOLTIP = "Allows previously exported regions to be reloaded";
    final static public String CHANGE_GENOME_TOOLTIP = "Switch the current genome";
    final static public String IMPORT_GENOME_TOOLTIP =
            "Create a user-defined genome and makes it available for use in the application";
    final static public String LOAD_GENOME_TOOLTIP =
            "Make an externally defined genome available for use in the application";
    final static public String REMOVE_USER_DEFINE_GENOME_TOOLTIP =
            "Removes user-defined genomes from the drop-down list";
    final static public String CLEAR_GENOME_CACHE_TOOLTIP =
            "Clears locally cached versions of IGV hosted genomes.";
    final static public String PREFERENCE_TOOLTIP = "Set user specific preferences";
    final static public String SHOW_ATTRIBUTE_DISPLAY_TOOLTIP = "Show or hide the attribute display";
    final static public String REFRESH_TOOLTIP = "Refresh the application's display";
    final static public String SHOW_HEATMAP_LEGEND_TOOLTIP = "IGVPanel or edit color legends and scales";
    final static public String SELECT_DISPLAYABLE_ATTRIBUTES_TOOLTIP = "Customize attribute display to show only checked attributes";
    final static public String DIRECT_DRAW_DISABLED_TOOLTIP = "Checked this item to prevent the use of direct draw" +
            " when rendering images - Uncheck it to use the default system behavior";
    final static public String SORT_TRACKS_TOOLTIP = "Sort tracks by attribute value";
    final static public String GROUP_TRACKS_TOOLTIP = "Group tracks";
    final static public String FILTER_TRACKS_TOOLTIP = "Filter tracks by attribute value";
    final static public String SET_DEFAULT_TRACK_HEIGHT_TOOLTIP = "Set the height for all tracks";
    final static public String FIT_DATA_TO_WINDOW_TOOLTIP = "Resizes all track heights in order to make all tracks visible in " +
            "their display with no vertical scrolling";
    final static public String HELP_TOOLTIP = "Open web help page";
    final static public String TUTORIAL_TOOLTIP = "Open tutorial web page";
    final static public String ABOUT_TOOLTIP = "Display application information";
    final static public String MACRO_SNAPSHOTS = "Macro Snapshots";
    final static public String RESET_FACTORY_TOOLTIP = "Restores all user preferences to their default settings.";

    private static File DEFAULT_USER_DIRECTORY;
    private static File DEFAULT_IGV_DIRECTORY;
    private static File GENOME_CACHE_DIRECTORY;
    private static File IGV_TEMP_DIRECTORY;
    public static final String IGV_DIR_USERPREF = "igvDir";

    public static int getDoubleClickInterval() {

        if (doubleClickInterval < 0) {
            try {
                Number obj = (Number) Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
                doubleClickInterval = obj.intValue();
            } catch (Exception e) {
                log.info("Error retrieving doubleClickInterval", e);
                doubleClickInterval = 500;
            }

        }
        return doubleClickInterval;
    }

    public static synchronized File getUserDirectory() {
        if (DEFAULT_USER_DIRECTORY == null) {
            DEFAULT_USER_DIRECTORY = FileSystemView.getFileSystemView().getDefaultDirectory();
        }
        return DEFAULT_USER_DIRECTORY;
    }

    public static File getIgvDirectory() {

        // Hack for know Java bug
        if (System.getProperty("os.name").equals("Windows XP")) {
            try {
                Runtime.getRuntime().exec("attrib -r \"" + getUserDirectory().getAbsolutePath() + "\"");
            } catch (IOException e) {
                // Oh well, we tried

            }
        }

        if (DEFAULT_IGV_DIRECTORY == null)

        {

            // See if an override is stored in preferences.  Try to create a directory if it is.  If there is an
            // error (the log is likely not available yet) and try to use the standard directory
            try {
                Preferences prefs = Preferences.userNodeForPackage(UIConstants.class);
                String userDir = prefs.get(IGV_DIR_USERPREF, null);
                if (userDir != null) {
                    DEFAULT_IGV_DIRECTORY = new File(userDir);
                    if (!DEFAULT_IGV_DIRECTORY.exists()) {
                        DEFAULT_IGV_DIRECTORY = null;
                        prefs.remove(IGV_DIR_USERPREF);
                    }
                }
            } catch (Exception e) {
                Preferences prefs = Preferences.userNodeForPackage(UIConstants.class);
                prefs.remove(IGV_DIR_USERPREF);
                System.err.println("Error creating user directory");
                e.printStackTrace();
            }

            // No overide, try the default place
            if (DEFAULT_IGV_DIRECTORY == null) {
                String userHomeString = System.getProperty("user.home");
                File rootDir = new File(userHomeString);
                if (!(rootDir.exists() && canWrite(rootDir))) {
                    rootDir = getUserDirectory();
                }
                if (UIConstants.IS_MAC) {
                    DEFAULT_IGV_DIRECTORY = new File(rootDir, ".igv");
                } else {
                    DEFAULT_IGV_DIRECTORY = new File(rootDir, "igv");
                }
                if (!DEFAULT_IGV_DIRECTORY.exists()) {
                    try {
                        DEFAULT_IGV_DIRECTORY.mkdir();
                    }
                    catch (Exception e) {
                        System.err.println("Error creating user directory");
                        e.printStackTrace();
                    }
                }
            }

            // The IGV directory either doesn't exist or isn't writeable.  This situation can arise with Windows Vista
            // and Windows 7 due to a Java bug (http://bugs.sun.com/view_bug.do?bug_id=4787931)
            if (!(DEFAULT_IGV_DIRECTORY.exists() && DEFAULT_IGV_DIRECTORY.canRead() && canWrite(DEFAULT_IGV_DIRECTORY))) {
                int option = JOptionPane.showConfirmDialog(null,
                        "<html>The default IGV directory (" + DEFAULT_IGV_DIRECTORY + ") " +
                                "cannot be accessed.  Click Yes to choose a new folder or No to exit.<br>" +
                                "This folder will be used to store user preferences and cached genomes.",
                        "IGV Directory Error", JOptionPane.YES_NO_OPTION);

                if (option == JOptionPane.YES_OPTION) {
                    final JFileChooser fc = new JFileChooser();
                    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                    int retValue = fc.showOpenDialog(null);
                    if (retValue == JFileChooser.APPROVE_OPTION) {
                        DEFAULT_IGV_DIRECTORY = fc.getSelectedFile();
                        Preferences prefs = Preferences.userNodeForPackage(UIConstants.class);
                        prefs.put(IGV_DIR_USERPREF, DEFAULT_IGV_DIRECTORY.getAbsolutePath());
                    }
                }
            }


            if (!DEFAULT_IGV_DIRECTORY.canRead()) {
                throw new DataLoadException("Cannot read from user directory", DEFAULT_IGV_DIRECTORY.getAbsolutePath());
            } else if (!canWrite(DEFAULT_IGV_DIRECTORY)) {
                throw new DataLoadException("Cannot write to user directory", DEFAULT_IGV_DIRECTORY.getAbsolutePath());
            }

            System.out.println("IGV directory: " + DEFAULT_IGV_DIRECTORY);

        }


        return DEFAULT_IGV_DIRECTORY;
    }

    private static boolean canWrite(File directory) {
        // There are bugs in Java window (targe fix is Java 7).  The only way to know for sure is to try to write something
        if (IS_WINDOWS) {
            File testFile = null;
            try {
                testFile = new File(directory, "igv332415dsfjdsklt.testfile");
                if (testFile.exists()) {
                    testFile.delete();
                }
                testFile.deleteOnExit();
                testFile.createNewFile();
                return testFile.exists();
            } catch (IOException e) {
                return false;
            } finally {
                if (testFile.exists()) {
                    testFile.delete();
                }
            }
        } else {
            return directory.canWrite();
        }

    }

    public static File getGenomeCacheDirectory() {
        if (GENOME_CACHE_DIRECTORY == null) {
            GENOME_CACHE_DIRECTORY = new File(getIgvDirectory(), Globals.GENOME_CACHE_FOLDER_NAME);
            if (!getGenomeCacheDirectory().exists()) {
                getGenomeCacheDirectory().mkdir();
            }
            if (!getGenomeCacheDirectory().canRead()) {
                throw new DataLoadException("Cannot read from user directory", getGenomeCacheDirectory().getAbsolutePath());
            } else if (!getGenomeCacheDirectory().canWrite()) {
                throw new DataLoadException("Cannot write to user directory", getGenomeCacheDirectory().getAbsolutePath());
            }
        }
        return GENOME_CACHE_DIRECTORY;
    }

    public static File getTmpDirectory() {
        if (IGV_TEMP_DIRECTORY == null) {
            String tmpDir = (System.getProperty("java.io.tmpdir"));
            IGV_TEMP_DIRECTORY = new File(tmpDir);
            if (!getTmpDirectory().exists()) {
                getTmpDirectory().mkdir();
            }
            if (!IGV_TEMP_DIRECTORY.canRead()) {
                throw new DataLoadException("Cannot read from user directory", getTmpDirectory().getAbsolutePath());
            } else if (!IGV_TEMP_DIRECTORY.canWrite()) {
                throw new DataLoadException("Cannot write to user directory", getTmpDirectory().getAbsolutePath());
            }

        }
        return IGV_TEMP_DIRECTORY;
    }


    /**
     * Field description
     */
    final public static String OVERWRITE_SESSION_MESSAGE =
            "<html>Opening a session will unload all current data. " + "<br>Are you sure you wish to continue?";
    /**
     * Field description
     */
    final public static String NEW_SESSION_MESSAGE =
            "<html>Creating a new session will unload all current data. " + "<br>Are you sure you wish to continue?";
    final public static String CANNOT_ACCESS_SERVER_GENOME_LIST = "The Genome server is currently inaccessible.";
    final public static String INVALID_SERVER_GENOME_LIST_HEADER = "Genomes cannot be retrieved from the server. " + "The server-side genome list is invalid!";
    // Session Folder

    /**
     * Field description
     */
    final public static int NUMBER_OF_RECENT_SESSIONS_TO_LIST = 3;
    /**
     * Field description
     */
    final public static String DEFAULT_SESSION_FILE = "igv_session" + Globals.SESSION_FILE_EXTENSION;
    // URLs
    /**
     * Field description
     */
    final static public String SERVER_BASE_URL = "http://www.broadinstitute.org/";
    /**
     * Field description
     */
    final public static String IGV_LOG_SERVER_URL = SERVER_BASE_URL + "igv/LogServlet";
    // Colors
    // float[] hsb = Color.RGBtoHSB(255, 255, 210, null);
    /**
     * Field description
     */
    final static public Color LIGHT_YELLOW = new Color(255, 244, 201);
    /**
     * Field description
     */
    final public static Color VERY_LIGHT_GRAY = new Color(238, 239, 240);
    /**
     * Field description
     */
    public static Color NO_DATA_COLOR = new Color(200, 200, 200, 150);
    // GENOME
    /**
     * Field description
     */
    final static public String IMPORT_GENOME_LIST_MENU_ITEM = "Import Genome...";
    /**
     * Field description
     */
    final static public String LOAD_GENOME_LIST_MENU_ITEM = "Load Genome...";
    /**
     * Field description
     */
    final static public String REMOVE_GENOME_LIST_MENU_ITEM = "Remove Imported Genomes...";
    /**
     * Field description
     */
    final static public String GENOME_LIST_SEPARATOR = "--SEPARATOR--";

}
