/*
 * This file is /include/FSutil.js
 *
 * It contains general purpose utility functions available for the tabs of the
 * FastScale UI
 */
function bin2hex( s )
{
    var     v;
    var     i;
    var     f = 0;
    var     a = [ ];

    s += '';
    f = s.length;
    for ( i = 0; i < f; i++ )
    {
        a[ i ] = s.charCodeAt( i ).toString( 16 ).replace(/^([\da-f])$/, "0$1");
    }
    return a.join( '' );
}


function CapitalizeFirstLetter( str )
{   // CapitalizeFirstLetter
    var     newVal = new Array( );
    var     words = str.split( " " );
    var     neswPattern = /^[n|s]\.?[e|w]\.?$/i;
    var     neswRegex = new RegExp( neswPattern );
    var     reResults;
    var     theWord;

    for ( var c = 0; c < words.length; c++ )
    {
        theWord = words[ c ];
        /*
            ne
            n.e.
            se
            s.e.
            sw
            s.w.
            nw
            n.w
        */
        if ( ( reResults = neswRegex.exec( theWord ) ) )
        {
            newVal[ c ] = theWord.replace( /\./g, "" ).toUpperCase( );
            continue;
        }
        if ( "PO" == theWord )
        {
            newVal[ c ] = theWord;
            continue;   // leave PO as in PO Box alone
        }

        var     upper = theWord.substr( 0, 1 ).toUpperCase( );
        var     lower = ( theWord.length > 1 ) ? theWord.substr( 1 ).toLowerCase( ) : "";

        newVal[ c ] = upper + lower;
    }
    return newVal.join( " " );
}   // CapitalizeFirstLetter

function ClearArray( arr )
{   // ClearArray
    while ( arr.length )
    {
        arr.pop( );
    }
}   // ClearArray

// general purpose function - based on that in util.inc (PHP) to convert a numeric
// value into a human friendly (rounded) value.
function decodeSize( bytes )
{
    var types = Array( 'B', 'KB', 'MB', 'GB', 'TB' );

    for( var i = 0; bytes >= 1024 && i < ( types.length - 1 ); bytes /= 1024, i++ )
    {
        ;
    }

    bytes = Math.round( bytes * 100 ) / 100;

    return( "" + bytes + " " + types[ i ] );
}

function EMC_FS_WrapALongString( elCell, oRecord, oColumn, oData )
{   // EMC_FS_WrapALongString
    if ( "undefined" == typeof oData )
    {
        return;
    }
    var     str;
    var     slen = ( "undefined" == typeof oColumn.splitlen ) ? 16
                : oColumn.splitlen;
    var     ndx = slen;

    str = oData.substr( 0, slen );
    while ( ndx < oData.length )
    {
        str += "<br>" + oData.substr( ndx, slen );
        ndx += slen;
    }

    elCell.innerHTML = str;
}   // EMC_FS_WrapALongString

function EscapeLTGT( str )
{   // EscapeLTGT
    var     newStr = str.replace( /</g, "&lt;" );
    return newStr.replace( />/g, "&gt;" );
}   // EscapeLTGT

function EscapePlusSign( str )
{   // EscapeLTGT
    return str.replace( /\+/g, "%2B" );
}   // EscapeLTGT

function EscapeSingleQuote( str )
{   // EscapeSingleQuote
    return str.replace( /'/g, "\\'" );
}   // EscapeSingleQuote

/*
 * This function does an array.indexOf( ) operation.  It is widely reputed that
 * IE does not support that function properly at all times.
 */
function FindItemInArray( needle, haystack )
{   // FindItemInArray
    if ( 0 == haystack.length )
    {
        return -1;
    }

    for ( var ndx = 0; ndx < haystack.length; ndx++ )
    {
        if ( needle == haystack[ ndx ] )
        {
            return ndx;
        }
    }
    return -1;
}   // FindItemInArray

function FormatOffsetTime( delta )
{   // FormatOffsetTime
    var     nowSortOf = new Date( );

    nowSortOf.setTime( nowSortOf.getTime( ) + delta * 1000 );
    return FormatTime( nowSortOf );
}   // FormatOffsetTime

function FormatTime( t )
{   // FormatTime
    var   curtime = ( "undefined" == typeof t ) ? new Date( ) : t;
    var   curhour = curtime.getHours( );
    var   curmin = curtime.getMinutes( );
    var   cursec = curtime.getSeconds( );
    var   time = "";

    time = curhour + ":";
    time += ( ( curmin < 10 ) ? "0" : "" ) + curmin;
    time += ":";
    time += ( ( cursec < 10 ) ? "0" : "" ) + cursec;

    return time;
}   // FormatTime

/*
 * GenerateRandomString is often called to create temporary passwords
 * For that reason, we are leaving out 0Oo 1l to avoid visual problems
 */
function GenerateRandomString( length )
{
    var     allowed = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789'.split( "" );

    if ( ! length )
    {
        length = Math.floor( Math.random( ) * allowed.length );
    }

    var     str = "";
    for ( var ndx = 0; ndx < length; ndx++)
    {
        var     jjj = Math.floor( Math.random( ) * allowed.length );
        var     lll = allowed[ jjj ];

        str += lll;
    }
    return str;
}

function ShowAPanel4nSeconds( title, seconds, options )
{   // ShowAPanel4nSeconds
    var     defaults =
    {
        width:          "240px",
        visible:        true,
        draggable:      true,
        fixedcenter:    true,
        close:          true,
        zindex:         5,
        modal:          false,
        context:        [ ]
    }

    ourPanel = new YAHOO.widget.Panel(
        "wait",
        {
            width: ( "undefined" == typeof options || "undefined" == typeof options[ "width" ] ) ? defaults[ "width" ]
                                                                                                 : options[ "width" ],
            visible: ( "undefined" == typeof options || "undefined" == typeof options[ "visible" ] ) ? defaults[ "visible" ]
                                                                                                     : options[ "visible" ],
            draggable: ( "undefined" == typeof options|| "undefined" == typeof options[ "draggable" ] ) ? defaults[ "draggable" ]
                                                                                                        : options[ "draggable" ],
            fixedcenter: ( "undefined" == typeof options || "undefined" == typeof options[ "fixedcenter" ] ) ? defaults[ "fixedcenter" ]
                                                                                                             : options[ "fixedcenter" ],
            close: ( "undefined" == typeof options || "undefined" == typeof options[ "close" ] ) ? defaults[ "close" ]
                                                                                                 : options[ "close" ],
            modal: ( "undefined" == typeof options || "undefined" == typeof options[ "modal" ] ) ? defaults[ "modal" ]
                                                                                                 : options[ "modal" ],
            context: ( "undefined" == typeof options || "undefined" == typeof options[ "context" ] ) ? defaults[ "context" ]
                                                                                                     : options[ "context" ]
        } );

    ourPanel.setHeader( title );
    ourPanel.setFooter( "This dialog will close in " + seconds + " seconds" );
    ourPanel.setBody( '<img src="/assets/progress.gif" />' );
    ourPanel.render( document.body );

    // Define the callback object for Connection Manager that will allow us
    // to hide the dialog when the time has expired
    var callback =
    {
        success : function( o )
        {
            ourPanel.hide( );
        },
        failure : function( o )
        {
            ourPanel.hide( );
        }
    }

    // Show the Panel
    ourPanel.show( );

    // Connect to our data source and load the data
    var     conn = YAHOO.util.Connect.asyncRequest( "POST",
                                                    "/json/util.json.php?function=sleepforseconds&seconds=" + seconds,
                                                    callback);
}   // ShowAPanel4nSeconds

function SortNoCase( arr )
{   // SortNoCase
    arr.sort( function( a, b )
              {
                var     x = a.toLowerCase( );
                var     y = b.toLowerCase( );

                if ( x > y )
                {
                    return 1;
                }
                if ( x < y )
                {
                    return -1;
                }
                return 0;   // equal
              }
            );
}   // SortNoCase

function StringIsAllNumeric( str )
{   // StringIsAllNumeric
    var     checkDigits = new RegExp( '^([0-9]+)$' );
    var     reResults = checkDigits.exec( str );

    if ( null == reResults )
    {
        return false;
    }
    else
    {
        return true;
    }
}   // StringIsAllNumeric

// convert a 1-6 digit hex string into a #RRGGBB HTML color specification
function strToHexColor( s )
{   // strToHexColor
    var     pad = "000000";
    var     arr = pad.split( "" );
    var     idx = 5;

    for ( var i = s.length-1; i >= 0 ; i-- )
    {
        arr[ idx ] = s.charAt( i );
        idx = idx - 1;
    }

    return "#" + arr.join("");
}   // strToHexColor

function TrimString( str )
{
    var     trimRE = /^\s+|\s+$/g;

    return str.replace( trimRE, "" );
}

function urlencode( str )
{   // urlencode
    // URL-encodes string
    //
    // version: 1102.614
    // discuss at: http://phpjs.org/functions/urlencode
    // +   original by: Philip Peterson
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: AJ
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: travc
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Lars Fischer
    // +      input by: Ratheous
    // +      reimplemented by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Joris
    // +      reimplemented by: Brett Zamir (http://brett-zamir.me)
    // %          note 1: This reflects PHP 5.3/6.0+ behavior
    // %        note 2: Please be aware that this function expects to encode into UTF-8 encoded strings, as found on
    // %        note 2: pages served as UTF-8
    // *     example 1: urlencode('Kevin van Zonneveld!');
    // *     returns 1: 'Kevin+van+Zonneveld%21'
    // *     example 2: urlencode('http://kevin.vanzonneveld.net/');
    // *     returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
    // *     example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
    // *     returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
    str = (str + '').toString();

    // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
    // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
    return encodeURIComponent( str ).replace(/!/g, '%21').
                                     replace(/'/g, '%27').
                                     replace(/\(/g, '%28').
                                     replace(/\)/g, '%29').
                                     replace(/\*/g, '%2A').
                                     replace(/%20/g, '+');
}   // urlencode

function ValidateeMailAddress( adr )
{   // ValidateeMailAddress
    var     eMailPattern = /^((?:(?:(?:[a-z0-9][\.\-\+_]?)*)[a-z0-9])+)\@((?:(?:(?:[a-z0-9][\.\-_]?){0,62})[a-z0-9])+)\.([a-z0-9]{2,6})$/i;
    var     eMailRegex = new RegExp( eMailPattern );
    var     reResults = eMailRegex.exec( adr );

    return ( null == reResults ) ? false : true;
}   // ValidateeMailAddress

function ValidateZIP( zip )
{   // ValidateZIP
    var     ZIPPattern = /^\s*((\d\d\d\d\d)(-\d\d\d\d)?)\s*$/;
    var     ZIPRegex = new RegExp( ZIPPattern );
    var     reResults = ZIPRegex.exec( zip );

    return ( null == reResults ) ? false : true;
}   // ValidateZIP

/*
 * This routine takes a string with an IP Address and checks it for validity.
 */
function VerifyIPAddress( adr )
{   // VerifyIPAddress
    var     IPRE = new RegExp( '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' );
    var     reResults = IPRE.exec( TrimString( adr ) );
    var     legit  = ( null == reResults ) ? false : true;
    var     IPAddress = {
                            "valid": false,
                            "IPAddress": "",
                            "octets": new Array( -1, -1, -1, -1 )
                        };

    if ( ! legit )
    {
        return IPAddress;
    }

    for ( var ndx = 0; ndx <= 3; ndx++ )
    {
        IPAddress.IPAddress += parseInt( reResults[ ndx + 1 ] );
        if ( 3 != ndx )
        {
            IPAddress.IPAddress += ".";
        }
        IPAddress.octets[ ndx ] = parseInt( reResults[ ndx + 1 ] );
    }
    IPAddress.valid = true;

    return IPAddress;
}   // VerifyIPAddress

/*
 * YUIAlert puts up a YUI panel to be used in place of the standard alert( )
 * function.  It is fully controllable most notably by the context parameter
 * that will place the panel wherever the caller deems necessary.
 */
function YUIAlert( text, options )
{   // YUIAlert
    var     defaults =
    {
        width:          "320px",
        visible:        true,
        draggable:      true,
        fixedcenter:    true,
        close:          true,
        zindex:         5,
        header:         "NCSSA",
        modal:          false,
        context:        [ ],
        container:      document.body
    }

    var     YUIPanel = new YAHOO.widget.Panel
    (
        "yuipanel",
        {
            width: ( "undefined" == typeof options || "undefined" == typeof options[ "width" ] ) ? defaults[ "width" ]
                                                                                                 : options[ "width" ],
            visible: ( "undefined" == typeof options || "undefined" == typeof options[ "visible" ] ) ? defaults[ "visible" ]
                                                                                                     : options[ "visible" ],
            draggable: ( "undefined" == typeof options|| "undefined" == typeof options[ "draggable" ] ) ? defaults[ "draggable" ]
                                                                                                        : options[ "draggable" ],
            fixedcenter: ( "undefined" == typeof options || "undefined" == typeof options[ "fixedcenter" ] ) ? defaults[ "fixedcenter" ]
                                                                                                             : options[ "fixedcenter" ],
            close: ( "undefined" == typeof options || "undefined" == typeof options[ "close" ] ) ? defaults[ "close" ]
                                                                                                 : options[ "close" ],
            modal: ( "undefined" == typeof options || "undefined" == typeof options[ "modal" ] ) ? defaults[ "modal" ]
                                                                                                 : options[ "modal" ],
            context: ( "undefined" == typeof options || "undefined" == typeof options[ "context" ] ) ? defaults[ "context" ]
                                                                                                     : options[ "context" ]
        } );

    YUIPanel.setHeader( ( "undefined" == typeof options || "undefined" == typeof options[ "header" ] ) ? defaults[ "header" ]
                                                                                                       : options[ "header" ] );
    YUIPanel.setBody( text );
    /*
     * The default is to have no footer.  The user can force a footer by defining
     * one in context, even if it is a blank string.
     */
    if ( "undefined" != typeof options && "undefined" != typeof options[ "footer" ] )
    {
        this.YUIPanel.setFooter( options[ "footer" ] );
    }
    var     whereToPlace;

    whereToPlace = ( "undefined" == typeof options || "undefined" == typeof options[ "container" ] ) ? defaults[ "container" ]
                                                                                                     : options[ "container" ];
    YUIPanel.render( whereToPlace );
}   // YUIAlert

function YUIAlertObject( text, counter, options )
{   // YUIAlertObject
    this.defaults =
    {
        width:          "320px",
        visible:        true,
        draggable:      true,
        fixedcenter:    true,
        close:          true,
        zindex:         5,
        header:         "NCSSA",
        modal:          false,
        context:        [ ],
        container:      document.body
    }

    this.options = options;
    this.counter = counter;
    this.YUIPanel = new YAHOO.widget.Panel
    (
        "yuipanel" + counter,
        {
            width: ( "undefined" == typeof options || "undefined" == typeof options[ "width" ] ) ? this.defaults[ "width" ]
                                                                                                 : options[ "width" ],
            visible: ( "undefined" == typeof options || "undefined" == typeof options[ "visible" ] ) ? this.defaults[ "visible" ]
                                                                                                     : options[ "visible" ],
            draggable: ( "undefined" == typeof options|| "undefined" == typeof options[ "draggable" ] ) ? this.defaults[ "draggable" ]
                                                                                                        : options[ "draggable" ],
            fixedcenter: ( "undefined" == typeof options || "undefined" == typeof options[ "fixedcenter" ] ) ? this.defaults[ "fixedcenter" ]
                                                                                                             : options[ "fixedcenter" ],
            close: ( "undefined" == typeof options || "undefined" == typeof options[ "close" ] ) ? this.defaults[ "close" ]
                                                                                                 : options[ "close" ],
            modal: ( "undefined" == typeof options || "undefined" == typeof options[ "modal" ] ) ? this.defaults[ "modal" ]
                                                                                                 : options[ "modal" ],
            context: ( "undefined" == typeof options || "undefined" == typeof options[ "context" ] ) ? this.defaults[ "context" ]
                                                                                                     : options[ "context" ]
        }
    );

    this.YUIPanel.setHeader( ( "undefined" == typeof options || "undefined" == typeof options[ "header" ] ) ? this.defaults[ "header" ]
                                                                                                            : options[ "header" ] );
    this.YUIPanel.setBody( text );
    /*
     * The default is to have no footer.  The user can force a footer by defining
     * one in context, even if it is a blank string.
     */
    if ( "undefined" != typeof options && "undefined" != typeof options[ "footer" ] )
    {
        this.YUIPanel.setFooter( options[ "footer" ] );
    }
    this.whereToPlace = ( "undefined" == typeof options || "undefined" == typeof options[ "container" ] ) ? this.defaults[ "container" ]
                                                                                                          : options[ "container" ];
    this.YUIPanel.render( this.whereToPlace );

    this.destroy = function( )
    {
        this.YUIPanel.destroy( );
    }

    this.hide = function( )
    {
        this.YUIPanel.hide( );
    }

    this.moveTo = function( x, y )
    {
        this.x = x;
        this.y = y;
        this.YUIPanel.moveTo( x, y );
    }

    this.moveToDelta = function( x, y )
    {
        this.x += x;
        this.y += y;
        this.YUIPanel.moveTo( this.x, this.y );
    }

    this.setBody = function( b )
    {
        this.YUIPanel.setBody( b );
    }

    this.setFooter = function( b )
    {
        this.YUIPanel.setFooter( b );
    }

    this.setHeader = function( b )
    {
        this.YUIPanel.setHeader( b );
    }

    this.show = function( )
    {
        this.YUIPanel.show( );
    }

}   // YUIAlertObject

function YUIProgressAlert( )
{   // YUIProgressAlert

    this.progressBar =  new YAHOO.widget.Panel( "YUIProgressBar",
                                                {
                                                    width:          "320px",
                                                    fixedcenter:    true,
                                                    close:          true,
                                                    draggable:      true,
                                                    zindex:         5,
                                                    modal:          false,
                                                    visible:        false
                                                } );

    this.progressBar.setHeader( "Initial Setting -- SHOULD NOT BE SEEN" );
    this.progressBar.setFooter( "Initial footer -- SHOULD NOT BE SEEN" );
    this.progressBar.setBody( '<img src="/assets/progress.gif" />' );
    this.progressBar.render( document.body );

}   // YUIProgressAlert

