/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
/**
 *
 @version $Id: Configuration.java 1798 2007-05-09 02:08:41Z dcollins $
 @author Tom Gaskins
 */
package gov.nasa.worldwind;

import java.util.*;
import java.io.*;

public class Configuration // Singleton
{
    private static final String CONFIG_FILE_NAME = "config/worldwind.properties";
    private static final String CONFIG_FILE_PROPERTY_KEY = "gov.nasa.worldwind.config.file";

    private static Configuration ourInstance = new Configuration();

    private static Configuration getInstance()
    {
        return ourInstance;
    }

    private Properties defaultSettings = new Properties();
    private Properties customSettings;

    private Configuration()
    {
        initializeDefaults();
        initializeCustom();
    }

    private void initializeDefaults()
    {
        defaultSettings.setProperty(AVKey.DATA_FILE_CACHE_CLASS_NAME, "gov.nasa.worldwind.BasicDataFileCache");
        defaultSettings.setProperty(AVKey.DATA_FILE_CACHE_CONFIGURATION_FILE_NAME, "config/DataFileCache.xml");
        defaultSettings.setProperty(AVKey.FRAME_CONTROLLER_CLASS_NAME, "gov.nasa.worldwind.BasicFrameController");
        defaultSettings.setProperty(AVKey.GLOBE_CLASS_NAME, "gov.nasa.worldwind.globes.Earth");
        defaultSettings.setProperty(AVKey.INPUT_HANDLER_CLASS_NAME, "gov.nasa.worldwind.awt.AWTInputHandler");
        defaultSettings.setProperty(AVKey.LOGGER_NAME, "gov.nasa.worldwind");
        defaultSettings.setProperty(AVKey.MEMORY_CACHE_CLASS_NAME, "gov.nasa.worldwind.BasicMemoryCache");
        defaultSettings.setProperty(AVKey.MODEL_CLASS_NAME, "gov.nasa.worldwind.BasicModel");
        defaultSettings.setProperty(AVKey.RETRIEVAL_SERVICE_CLASS_NAME, "gov.nasa.worldwind.BasicRetrievalService");
        defaultSettings.setProperty(AVKey.SCENE_CONTROLLER_CLASS_NAME, "gov.nasa.worldwind.BasicSceneController");
        defaultSettings.setProperty(AVKey.THREADED_TASK_SERVICE_CLASS_NAME, "gov.nasa.worldwind.ThreadedTaskService");
        defaultSettings.setProperty(AVKey.VIEW_CLASS_NAME, "gov.nasa.worldwind.BasicOrbitView");
        defaultSettings.setProperty(AVKey.LAYERS_CLASS_NAMES,
            "gov.nasa.worldwind.layers.Earth.BMNGSurfaceLayer"
                + ",gov.nasa.worldwind.layers.Earth.LandsatI3"
                + ",gov.nasa.worldwind.layers.Earth.USGSUrbanAreaOrtho"
                + ",gov.nasa.worldwind.layers.Earth.EarthNASAPlaceNameLayer"
                + ",gov.nasa.worldwind.layers.CompassLayer"
        );

        defaultSettings.setProperty(AVKey.INITIAL_LATITUDE, "0");
        defaultSettings.setProperty(AVKey.RETRIEVAL_POOL_SIZE, "5");
        defaultSettings.setProperty(AVKey.RETRIEVAL_QUEUE_SIZE, "200");
        defaultSettings.setProperty(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, "9000");
        defaultSettings.setProperty(AVKey.THREADED_TASK_POOL_SIZE, "1");
        defaultSettings.setProperty(AVKey.THREADED_TASK_QUEUE_SIZE, "5");
        defaultSettings.setProperty(AVKey.VERTICAL_EXAGGERATION, "1");
        defaultSettings.setProperty(AVKey.CACHE_SIZE, "2000000000");
        defaultSettings.setProperty(AVKey.CACHE_LOW_WATER, "140000000");
        defaultSettings.setProperty(AVKey.URL_CONNECT_TIMEOUT, "8000"); // milliseconds
        defaultSettings.setProperty(AVKey.URL_READ_TIMEOUT, "5000"); // milliseconds
    }

    private void initializeCustom()
    {
        this.customSettings = new Properties(defaultSettings);

        String configFileName = System.getProperty(CONFIG_FILE_PROPERTY_KEY, CONFIG_FILE_NAME);
        try
        {
            InputStream propsStream = this.getClass().getResourceAsStream("/" + configFileName);
            if (propsStream == null)
            {
                File propsFile = new File(configFileName);
                if (propsFile.exists())
                {
                    propsStream = new FileInputStream(propsFile);
                }
                else
                {
                    String message = WorldWind.retrieveErrMsg("Configuration.UnavailablePropsFile" + configFileName);
                    WorldWind.logger().log(java.util.logging.Level.FINE, message);
                }
            }

            if (propsStream != null)
            {
                this.customSettings.load(propsStream);
            }
        }
        catch (FileNotFoundException e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.UnavailablePropsFile" + configFileName);
            WorldWind.logger().log(java.util.logging.Level.FINE, message);
        }
        catch (IOException e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.ExceptionReadingPropsFile" + configFileName);
            WorldWind.logger().log(java.util.logging.Level.FINE, message);
        }
        catch (Exception e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.ExceptionReadingPropsFile" + configFileName
                + " " + e.getLocalizedMessage());
            WorldWind.logger().log(java.util.logging.Level.FINE, message, e);
        }
    }

    public static String getStringValue(String key, String defaultValue)
    {
        String v = getStringValue(key);
        return v != null ? v : defaultValue;
    }

    public static String getStringValue(String key)
    {
        return getInstance().customSettings.getProperty(key);
    }

    public static Integer getIntegerValue(String key, Integer defaultValue)
    {
        Integer v = getIntegerValue(key);
        return v != null ? v : defaultValue;
    }

    public static Integer getIntegerValue(String key)
    {
        String v = getStringValue(key);
        if (v == null)
            return null;

        try
        {
            return Integer.parseInt(v);
        }
        catch (NumberFormatException e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.ConversionError" + v);
            WorldWind.logger().log(java.util.logging.Level.FINE, message);

            return null;
        }
    }

    public static Long getLongValue(String key, Long defaultValue)
    {
        Long v = getLongValue(key);
        return v != null ? v : defaultValue;
    }

    public static Long getLongValue(String key)
    {
        String v = getStringValue(key);
        if (v == null)
            return null;

        try
        {
            return Long.parseLong(v);
        }
        catch (NumberFormatException e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.ConversionError" + v);
            WorldWind.logger().log(java.util.logging.Level.FINE, message);

            return null;
        }
    }

    public static Double getDoubleValue(String key, Double defaultValue)
    {
        Double v = getDoubleValue(key);
        return v != null ? v : defaultValue;
    }

    public static Double getDoubleValue(String key)
    {
        String v = getStringValue(key);
        if (v == null)
            return null;

        try
        {
            return Double.parseDouble(v);
        }
        catch (NumberFormatException e)
        {
            String message = WorldWind.retrieveErrMsg("Configuration.ConversionError" + v);
            WorldWind.logger().log(java.util.logging.Level.FINE, message);

            return null;
        }
    }

    public static boolean hasKey(String key)
    {
        return getInstance().customSettings.contains(key);
    }

    public static void removeKey(String key)
    {
        getInstance().customSettings.remove(key);
    }

    public static void setValue(String key, Object value)
    {
        getInstance().customSettings.put(key, value.toString());
    }

    // OS, user, and run-time specific system properties. //

    public static String currentWorkingDirectory()
    {
        String dir = System.getProperty("user.dir");
        return (dir != null) ? dir : ".";
    }

    public static String getUserHomeDirectory()
    {
        String dir = System.getProperty("user.home");
        return (dir != null) ? dir : ".";
    }

    public static String systemTempDirectory()
    {
        String dir = System.getProperty("java.io.tmpdir");
        return (dir != null) ? dir : ".";
    }

    public static boolean isMacOS()
    {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("mac");
    }

    public static boolean isWindowsOS()
    {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("windows");
    }

    public static boolean isLinuxOS()
    {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("linux");
    }

    public static boolean isUnixOS()
    {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("unix");
    }

    public static boolean isSolarisOS()
    {
        String osName = System.getProperty("os.name");
        return osName != null && osName.toLowerCase().contains("solaris");
    }
}
