/**
 * Debug.java
 * Copyright 2007 - 2008 Zach Scrivena
 * zachscrivena@gmail.com
 * http://zs.freeshell.org/
 *
 * TERMS AND CONDITIONS:
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.freeshell.zs.common;

import java.io.Console;
import java.io.PrintWriter;
import java.util.Date;


/**
 * Perform debugging-related operations.
 */
public class Debug
{
    /** standard error output stream */
    private static PrintWriter err;


    /**
    * Static initialization block.
    */
    static
    {
        final Console c = System.console();

        if (c == null)
        {
            err = new PrintWriter(System.out);
        }
        else
        {
            err = c.writer();
        }
    }


    /**
    * Print the string representation of the specified object
    * to the standard error output stream.
    *
    * @param o
    *     object to the printed
    */
    public static void p(
            final Object o)
    {
        err.println(o + "");
        err.flush();
    }


    /**
    * Print the string representation of the specified object
    * to the standard error output stream, with a timestamp.
    *
    * @param o
    *     object to the printed
    */
    public static void pt(
            final Object o)
    {
        err.println(new Date() + ": " + o);
        err.flush();
    }


    /**
    * Get a string representation of the stack trace for the specified exception.
    *
    * @param ex
    *      exception
    * @return
    *      string representation of the stack trace
    */
    public static String getStackTraceString(
            final Exception ex)
    {
        final StringBuilder sb = new StringBuilder("Exception stack trace:");

        for (StackTraceElement e : ex.getStackTrace())
        {
            sb.append("\n  ");
            sb.append(e);
        }

        return sb.toString();
    }


    /**
    * Get a string representation of the system information (OS, JRE, JVM).
    *
    * @return
    *     string representation of the system information
    */
    public static String getSystemInformationString()
    {
        return "System Information:" +
                "\n  " + getSystemProperty("os.name") + " (" + getSystemProperty("os.version") + ", " + getSystemProperty("os.arch") + ")" +
                "\n  JRE " + getSystemProperty("java.version") + " (" + getSystemProperty("java.vendor") + ")" +
                "\n  " + getSystemProperty("java.vm.name") + " " + getSystemProperty("java.vm.version") + " (" + getSystemProperty("java.vm.vendor") + ")";
    }


    /**
    * Get the specified system property, without throwing any exceptions.
    *
    * @param key
    *     key of the system property to be obtained
    * @return
    *     String representation of the specified system property
    */
    public static String getSystemProperty(
            final String key)
    {
        try
        {
            return System.getProperty(key);
        }
        catch (Exception e)
        {
            return "Failed to get system property \"" + key + "\" (" + e + ")";
        }
    }


    /**
    * Set the specified system property, without throwing any exceptions.
    *
    * @param key
    *     key of the system property to be set
    * @param value
    *     value of the system property
    */
    public static void setSystemProperty(
            final String key,
            final String value)
    {
        try
        {
            System.setProperty(key, value);
        }
        catch (Exception e)
        {
            /* ignore */
        }
    }


    /**
    * Sleep for the specified number of milliseconds.
    * This method uses the Thread.sleep() method, but will ignore the InterruptedException
    * exception if thrown.
    *
    * @param millis
    *     number of milliseconds to sleep
    */
    public static void sleep(
            final long millis)
    {
        try
        {
            Thread.sleep(millis);
        }
        catch (InterruptedException e)
        {
            /* ignore */
        }
    }
}