/**
 * @library BeaPortalConsole
 *
 * This JavaScript library implements a simple pseudo-console that can be used to dump debugging or monitoring
 * information when writing new JavaScript libraries and code.
 *
 * All comments in this file may be removed when optimizing for production (though this library generally need not
 * be included in a production system).
 */

/**
 * The primary console instance.
 *
 * @access public
 */
var beaPortalConsole = new BeaPortalConsole();

/**
 * Creates a new BeaPortalConsole instance.  Console window creation properties should be set before calling methods
 * on the console, as setting them after any call will cause them to be ignored.
 *
 * @constructor
 * @access public
 *
 * @property target
 *      The name of the target window in which to open the console;
 *      defaults to "BeaPortalConsole"
 * @property url
 *      The initial url for the console document;
 *      defaults to "about:blank"
 * @property toolbar
 *      Whether or not a toolbar should be displayed in the console window; values may be "yes" or "no";
 *      defaults to "no"
 * @property width
 *      The width of the console window in pixels;
 *      defaults to "640"
 * @property height
 *      The height of the console window in pixels;
 *      defaults to "480"
 * @property directories
 *      Whether or not directories should be displayed in the console window; values may be "yes" or "no";
 *      defaults to "no"
 * @property status
 *      Whether or not a  statusbar should be displayed in the console window; values may be "yes" or "no";
 *      defaults to "no"
 * @property scrollbars
 *      Whether or not scrollbars should be displayed in the console window; values may be "yes" or "no";
 *      defaults to "yes"
 * @property resize
 *      Whether or not the console window should be resizable; values may be "yes" or "no";
 *      defaults to "yes"
 * @property menubar
 *      Whether or not a menubar should be displayed in the console window; values may be "yes" or "no";
 *      defaults to "no"
 * @property useBackgroundColors
 *      Whether or not lines should use associated background colors (if any);
 *      defaults to true
 */
function BeaPortalConsole()
{
    // "Public" methods
    this.println = beaPortalConsolePrintln;
    this.message = beaPortalConsoleMessage;
    this.assert = beaPortalConsoleAssert;
    this.error = beaPortalConsoleError;
    this.debug = beaPortalConsoleDebug;
    this.show = beaPortalConsoleShow;

    // "Private" methods
    this.createDocument = beaPortalConsoleCreateDocument;

    // "Private" member variables
    this.document = null;
    this.table = null;

    // Properties
    this.target = "BeaPortalConsole";
    this.url = "about:blank";
    this.toolbar = "no";
    this.width = "640";
    this.height= "480";
    this.directories = "no";
    this.status = "no";
    this.scrollbars = "yes";
    this.resize = "yes";
    this.menubar = "no";
    this.useLineBackgroundColors = true;
}

/**
 * Prints a message, followed by an HTML line break.
 *
 * @method BeaPortalConsole.println
 * @access public
 *
 * @param object
 *      The object to print (converted to a string)
 * @param (bgcolor)
 *      The background color for the line; defaults to
 */
function beaPortalConsolePrintln(object, bgcolor)
{
    this.createDocument();
    bgcolor = (bgcolor && this.useLineBackgroundColors ? " background-color: " + bgcolor + ";" : "");
    this.document.write("<div style='font-family: sans-serif; margin: 0px; padding: 2px;" + bgcolor + "'>" + object + "</div>\n");
}

/**
 * Prints a message, formatted with a type.
 *
 * @method BeaPortalConsole.message
 * @access public
 *
 * @param message
 *      An error message to display
 * @param (type)
 *      The type of the message (e.g. "ERROR", "DEBUG", etc); defaults to "MESSAGE"
 * @param (bgcolor)
 *      The background color for the line; defaults to
 *
 * @see #println(...)
 */
function beaPortalConsoleMessage(message, type, bgcolor)
{
    message = (message ? message : "(No detail)");
    type = (type ? type : "MESSAGE");
    this.println("<b>[" + type + "]</b> " + message, bgcolor);
}

/**
 * Prints an error message if the assertion statement (boolean) fails.
 *
 * @method BeaPortalConsole.assert
 * @access public
 *
 * @param pass
 *      A boolean assertion statement
 * @param message
 *      A message to display if the assertion fails (i.e. pass == false)
 *
 * @see #message(...)
 */
function beaPortalConsoleAssert(pass, message)
{
    if (!pass)
    {
        message = (message ? message : "(No detail)");
        this.error("<span style='font-weight: bold;'>Assertion failed: " + message + "</span>");
    }
}

/**
 * Prints an error message.
 *
 * @method BeaPortalConsole.error
 * @access public
 *
 * @param message
 *      An error message to display
 *
 * @see #message(...)
 */
function beaPortalConsoleError(message)
{
    this.message(message, "<span style='color: #ff0000;'>ERROR</span>", "#ffcccc");
}

/**
 * Prints a debug message.
 *
 * @method BeaPortalConsole.debug
 * @access public
 *
 * @param message
 *      A debug message to display
 *
 * @see #message(...)
 */
function beaPortalConsoleDebug(message)
{
    this.message(message, "<span style='color: #0000ff;'>DEBUG</span>", "#ccccff");
}

/**
 * Prints all properties of an object.
 *
 * @method BeaPortalConsole.show
 * @access public
 *
 * @param object
 *      The object for which properties should be displayed
 * @param (sort)
 *      The sort function to use when sorting properties; default is lexigraphic order
 *
 * @see #message(...)
 */
function beaPortalConsoleShow(object, sort)
{
    if (object)
    {
        var properties = new Array();
        var index = 0;

        for (property in object)
        {
            var key = new String(property);

            // @review Work around a Firefox 0.8 bug
            /*
            if (key != "domConfig")
            {
                var value = object[key];
                properties[index++] = new Array(property, value);
            }
            */
            try {
                var value = object[key];
            }
            catch (e) {
            	var value = "!!! Can't access property: " + e;
            }
            properties[index++] = new Array(property, value);
        }

        if (sort)
        {
            properties.sort(sort);
        }
        else
        {
            properties.sort();
        }

        var message = "<span style='font-weight: bold;'>" + (object.nodeName ? object.nodeName : object) + "</span>";
        this.message(message, "<span style='color: #006600;'>SHOW</span>", "#cce5cc");

        for (var i = 0; i < properties.length; i++)
        {
            var property = properties[i];
            var display = "<b>" + property[0] + ":</b> " + property[1];
            this.message(display, "<span style='color: #009966;'>PROPERTY</span>", "#e5ffe5");
        }
    }
}

/**
 * Opens a new console window (if it doesn't already exist) and initializes this class's "document" member variable.
 *
 * @method BeaPortalConsole.createDocument
 * @access private
 */
function beaPortalConsoleCreateDocument()
{
    if (!this.document)
    {
        var windowSpec = "toolbar=" + this.toolbar
                       + ", width=" + this.width
                       + ", height=" + this.height
                       + ", directories=" + this.directories
                       + ", status=" + this.status
                       + ", scrollbars=" + this.scrollbars
                       + ", resize=" + this.resize
                       + ", menubar=" + this.menubar;
        var console = window.open(this.url, this.target, windowSpec);

        if (console)
        {
            this.document = console.document;
        }
        else
        {
            window.alert("Attempt to open console window failed!");
        }
    }
}
