//****************************************************************************

// this should be false in production use
var debug = get_value( 'debug', false );
var debug_regex; // = new RegExp("add_list");
var limits = [ 10, 20, 40, 70, 80, 100, 200 ];
var current_rpc_id = new Array();

function unique_id( namespace ) {
    if ( typeof( namespace ) == 'undefined' ) namespace = '';
    else namespace += '_';
    // <b>very probably</b> unique id
    return namespace + (new String( Math.random() )).replace(/0\./,'');
};

function tidy_string( str ) {
	str = str.replace(/^\s*|\s*$/g, '');
	str = str.replace(/^"|"*;$/g, '');
	return str;
}

function string_trim( string ) {
    return string.trim();
}

// string object trim function
String.prototype.trim = function() {
    // return this.replace( /(?:(?:^|\n)\s+|\s+(?:$|\n))/g, '' );
    return this.replace( /(?:^(?:\s|\r|\n)*|(?:\s|\r|\n)*$)/g, '' );
}

function send_rpc( parameter_ar, callback_fn ) {

    var url = 'rpc.php';

    var rpc_id = null;
    var rpc_class = null;
    for ( var p in parameter_ar ) {
        var temp;
        if ( temp = parameter_ar[p].match( /^rpc_class=([^&]*)/ ) ) {
            rpc_class = temp[1];
        }
        if ( temp = parameter_ar[p].match( /^rpc_id=([^&]*)/ ) ) {
            rpc_id = temp[1];
        }
    }
    if ( rpc_id != null && rpc_class != null ) {

        // if this is the first invocation under the current id
        if ( window.current_rpc_id[rpc_class] != rpc_id ) {
            // then register this id
            window.current_rpc_id[rpc_class] = rpc_id;
            // and start the UI working spinner
            start_spinner( rpc_class );
        }
    }

    var payload = parameter_ar.join( '&' );

    logit(
        'send_rpc: <a href="'
            + url + '?' + payload
            + '">'
            + url + '?' + payload
            + '</a>'
    );

    var httpObj = get_httpObj();
    httpObj.open('POST', url, true);
    httpObj.setRequestHeader(
        'Content-Type',
        'application/x-www-form-urlencoded'
    );
    httpObj.send( payload );
    httpObj.onreadystatechange = function() {
        if (httpObj.readyState == 4) {
            var callbackObj;
            try {
                callbackObj = eval( httpObj.responseText );
            }
            catch( e ) {

                if ( window.debug ) {
                    logit(
                        'send_rpc::error: ' + e + '\n'
                      + 'send_rpc::result: '
                      + string_trim( httpObj.responseText )
                    );
                }
                callbackObj = httpObj.responseText;
            }
            callback_fn( callbackObj );
        }
    }
    return;
}

function get_httpObj() {
   try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
   try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
   try { return new XMLHttpRequest(); } catch(e) {}
   return null;
}

function confirm_removal( message, item_id ) {
    if ( confirm( message ) ) {
        var item = domElement( item_id );
        if ( item.parentNode ) {
            item.parentNode.removeChild( item );
        }
    }
    return;
}

function verify_image_validation_code( code, callback_func ) {
    var params = new Array();
    params.push( 'code=' + escape( code ) );
    params.push( 'rpc_class=verify_code' );
    send_rpc( params, callback_func );
    return;
}

// simple client side logging just appends to the body
function logit( value ) {
    if ( window.debug ) {
        if ( typeof( value ) == 'object' ) {
            var newValue = typeof( value ) + '::{\n';
            for ( var x in value ) {
                newValue += '\t' + x + ' => ' + value[x] + '\n';
            }
            value = newValue + '};'
        } else {
            if ( value && value.trim ) value = '[' + value.trim() + ']\n';
        }

        if ( window.debug_regex
          && !value.match( window.debug_regex )
        ) return;

        var thePre = document.createElement( 'pre' );
        if ( value.match( /send_rpc/ ) ) {
            thePre.innerHTML = value;
        }
        else {
            thePre.appendChild( document.createTextNode( value ) );
        }

        document.body.appendChild( thePre );
    }
    return;
}

// May return an array of items
// if the provided id doesn't match any uniquely id'd field.
function domElement( id ) {
    var element;
    // get a signle element
    if ( document.getElementById ) {
        element = document.getElementById(id);
    } else
        if ( document.all ) {
            element = document.all[id];
        }
    if ( element && element.id == id ) {
        return element;
    }
    // check
    var elements = new Array();
    for ( var i = 0; i < document.forms.length; i++ ) {
        if ( document.forms[i][id] ) {
            if ( document.forms[i][id].length ) {
                for (var j = 0; j < document.forms[i][id].length; j++) {
                    elements.push(document.forms[i][id][j]);
                }
            } else {
                elements.push(document.forms[i][id]);
            }
        }
    }
    if ( elements.length == 1 ) {
        return elements[0];
    } else
        if ( elements.length ) {
            return elements;
        }
    return undefined;
}

// This adds items to a UL and is a standard tool of an RPC callback
function add_list_items( list_type, rpc_response, purge, ul_classname ) {

    var items_added_count = 0;

    // don't do anything with bum data
    if ( !rpc_response || !rpc_response.list_items ) return;

    // purge the list of all current items if specified
    if ( typeof( purge ) == 'undefined' ) {
        purge = false;
    }
    else {
        purge = ( purge == 'purge' );
    }

    var list_items_column = domElement( list_type + '_list_column' );
    if ( !list_items_column ) {
        // if no list column, then check for a list row
        var list_items_row = domElement( list_type + '_list_row' );
        if ( list_items_row ) {
            // if purging then remove all the lists
            if ( purge ) {
                while ( list_items_row.firstChild ) {
                    list_items_row.removeChild( list_items_row.firstChild );
                }
            }
            // add fresh empty td to serve as the item list column
            list_items_column = document.createElement( 'td' );
            list_items_column.style.verticalAlign = 'top';
            list_items_row.appendChild( list_items_column );
        }
        // no list column or row found
        else {
            logit(
                'add_list_items: '
                + list_type
                + '_list_[column|row] absent'
            );
            return;
        }
    }

    // list item ids are assumed to be like: id="listnamekeyword_123"
    var id_regex = new RegExp('id="(' + list_type + '_[\\d]+)"');
    // logit( 'add_list_items: id_regex => ' + id_regex );

    var the_ul;
    var the_uls = list_items_column.getElementsByTagName( 'UL' );
    if ( the_uls ) the_ul = the_uls[0];
    if ( the_ul && the_ul.getElementsByTagName ) {
        if ( purge ) {
            while ( the_ul.firstChild ) {
                the_ul.removeChild( the_ul.firstChild );
            }
        }
        else {
            // remove any disappointment items
            //     or all of them if in purge mode
            var the_li = the_ul.getElementsByTagName( 'LI' );
            for ( var s in the_li ) {
                if ( the_li[s].className == 'disappointment' ) {
                    try {
                        the_li[s].parentNode.removeChild( the_li[s] );
                    } catch(e) {}
                }
            }
        }
    } else {
        the_ul = document.createElement( 'UL' );
        if ( typeof( ul_classname ) != 'undefined' ) {
            the_ul.className = ul_classname;
        }
        list_items_column.appendChild( the_ul );
    }

    // add the LIs one at a time to ensure no duplications
    for ( var s in rpc_response.list_items ) {
        var theId = rpc_response.list_items[s].match( id_regex );
        if ( theId == null || !theId || !theId[1] ) {
            // logit(
            //     'add_list_items: no id match for '
            //     + id_regex + ' on . . .\n\t'
            //     + rpc_response.list_items[s]
            // );
            theId = null;
        }
        if ( theId == null || !domElement( theId[1] ) ) {
            //logit(
            //    'accepted new node['
            //    + ( theId != null ? theId[1] : null )
            //    + ']: '
            //    + rpc_response.list_items[s]
            //);
            the_ul.innerHTML += rpc_response.list_items[s];
            items_added_count++;
        }
        else {
            // make a note of any rejected nodes
            logit( 'rejected duplicate: ' + rpc_response.list_items[s] );
        }
    }

    // Make the item selectors visible if applicable
    if ( rpc_response.list_items
      && rpc_response.list_items.length
      && rpc_response.list_items.length > 0
      && !rpc_response.list_items[0].match(/no results/)
    ) {
        // Select: all none invert
        var item_selectors = domElement( list_type + '_selectors');
        if ( item_selectors ) {
            item_selectors.style.display = 'block';
        }
    }

    // normal exit condition
    return items_added_count;
}

// This is the action for the standard list selector options
// Select: all none invert remove
function select_items( item_type, selection_type ) {
    var dom_column = domElement( item_type + '_list_column' );
    var the_checkbox = dom_column.getElementsByTagName('INPUT');
    if ( !the_checkbox || the_checkbox.length == 0 ) {
        var selectors = domElement( item_type + '_selectors');
        if ( selectors ) selectors.style.display = 'none';
        return;
    }
    for ( var es in the_checkbox ) {
        if ( !the_checkbox[es] ) continue;
        switch ( selection_type ) {
            case 'all': {
                the_checkbox[es].checked = true;
                break;
            }
            case 'none': {
                the_checkbox[es].checked = false;
                break;
            }
            case 'invert': {
                // the checkbox never lies
                the_checkbox[es].checked = (
                    the_checkbox[es].checked == false
                );
                break;
            }
            case 'remove': {
                if ( the_checkbox[es].checked == true ) {
                    var theLi = domElement(
                        item_type + '_' + the_checkbox[es].value
                    );
                    if (theLi) {
                        try {
                            theLi.parentNode.removeChild( theLi );
                        } catch(e) {}
                        // recurse rather than iterate due to funky behavior
                        // which results from iterating over a list
                        // the size of which is changing
                        return select_items( item_type, selection_type );
                    }
                }
                break;
            }
        }
    }
    return;
}

function set_temporary_status_message( message ) {

    var temp_status_message = domElement( 'temp_status_message' );
    if ( !temp_status_message ) {
        temp_status_message = document.createElement( 'div' );
        temp_status_message.setAttribute( 'id', 'temp_status_message' );
        temp_status_message.style.display = 'none';
        temp_status_message.style.top = '-200px';
        temp_status_message.style.left = '20px';
        temp_status_message.style.position = 'fixed';
        temp_status_message.style.visibility = 'visible';
        temp_status_message.style.backgroundColor = '#0000ff';
        temp_status_message.style.color = '#fff';
        temp_status_message.style.fontWeight = 'bold';
        temp_status_message.style.padding = '10px';
        document.body.appendChild( temp_status_message );
    }
    if ( typeof( message ) == 'undefined' ) {
        temp_status_message.style.top = '-200px';
        temp_status_message.style.display = 'none';
        temp_status_message.innerHTML = message;
    }
    else {
        temp_status_message.innerHTML = message;
        temp_status_message.style.top = '20px';
        temp_status_message.style.display = 'block';
        // will unset in three seconds
        setTimeout( 'set_temporary_status_message()', 3000 );
    }
    return;
}

function build_select_for( values, selected_value, styles ) {

    if ( typeof( styles ) == 'undefined' ) styles = null;

    var theSelect = document.createElement( 'select' );
    if ( styles != null ) {
        for ( var s in styles ) {
            theSelect.style[ styles[s].name ] = styles[s].value;
        }
    }

    // decide if selected value is by label or value
    var selected_by = '(value)';
    if ( isNaN( parseInt( selected_value ) ) ) {
        // TODO : another deciding factor is if values are provided
        selected_by = '(label)';
    }

    for ( var i in values ) {

        var label,value;
        if ( typeof( values[i] ) == 'object'
          && values[i].length
          && values[i].length == 2
        ) {
            label = values[i][1];
            value = values[i][0];
        }
        else {
            label = values[i];
            value = i;
        }
        var selected = (
            selected_value == eval( selected_by )
            ? ' selected="selected"'
            : ''
        );
        theSelect.innerHTML
            += '<option value="'
                + value
                + '"'
                + selected
                + '>'
                + label
                + '</option>';
    }
    return theSelect;
}

// This provides a convenient way of fetching the value of a form field
// regardless of its type ( i.e. select, checkbox, etc... )
function get_value_for_field( form_input ) {
    var value;
    if ( form_input ) {

// logit(
//     'get_value_for_field(typeof(form_input) => ' 
//     + typeof( form_input ) + ','
//     + 'form_input.length => '
//     + form_input.length
//     + ')'
// );
        if ( form_input.length ) {
            if ( form_input.length == 0 ) return;

            // base cases
            if ( form_input.nodeValue ) return form_input.nodeValue;
            else 
                if ( form_input.value ) return form_input.value;

            // return a single string for form item list of one items
            if ( form_input.length == 1 ) {
                value = get_value_for_field( form_input[0] );
            }
            // for a multiple item list prepare an array of results
            else {
                value = new Array();
                for ( var i = 0; i < form_input.length; i++ ) {

                    var temp = get_value_for_field( form_input[i] );
                    if ( temp ) {
                        value.push( temp );
                    }
                }
            }
        }
        else if ( form_input.nodeName ) {
    
            switch ( form_input.nodeName ) {
                case 'SELECT': {
                    value = form_input[form_input.selectedIndex].value;
                    break;
                }
                case 'OPTION': {
                    if ( form_input.selected ) {
                        value = form_input.value;
                        if ( !value ) value = form_input.innerHTML;
                    }
                    break;
                }
                case 'INPUT': {
                    switch ( form_input.type ) {
                        case 'text': {
                            value = form_input.value;
                            break;
                        }
                        case 'radio': {
                            if ( form_input.checked ) {
                                value = form_input.value;
                            }
                            break;
                        }
                        case 'checkbox': {
                            if ( form_input.checked ) {
                                value = form_input.value;
                            }
                            break;
                        }
                    }
                    break;
                }
            }
        }
        else {
            logit( 'get_value_for_field: uknown(' + form_input + ')' );
        }
    }
    else {
        logit( 'get_value_for_field: ERROR => (' + form_input + ') no value' );
    }
    return value;
}

// This gets the specified value from the query string
function get_value( name, default_value ) {

    var url = (new String( document.location )).split( '?' );
    var uri = url[1];
        url = url[0];

    if (uri) {

        var params = uri.split( '&' );
        var param = '';

        for ( var i in params ) {

            param = params[i].split( '=' );

            if ( param[0] == name ) return param[1];
        }
    }

    if ( name == 'x' || name == 't' ) {

        url = url.toLowerCase();
        url = url.replace( /index\.php$/, '' );
        url = url.replace( /\/$/,         '' );
        url = url.replace( /^http:\/\//,  '' );
        url = url.replace( /\/dev/,       '' );
        url = url.split( '/' );

        // case of: http://vwnames.com/paramvalue
        if ( url.length == 2 ) return url[1];
    }

    return default_value;
}

function get_root_directory() {
    var root_dir = '/';
    var url = (new String( document.location )).split( '?' )[0];
    url = url.replace( /^http:\/\//,  '' );
    var dirs = url.split( '/' );
    if ( dirs.length > 1 && dirs[1] == 'dev' ) dirs.pop();
    if ( dirs.length > 1 ) {
        var tabs_regex = /(home|request|search|faq|about|privacy|terms)/;
        var tab = dirs[1].match( tabs_regex ); 
        if ( !tab || tab == null ) {
            root_dir += dirs[1] + '/';
        }
    }
    return root_dir;
}

function generate_page_links(
    start,
    current_page_number,
    results_per_page,
    total_results_available,
    query_string
) {

    // logit( 'generate_page_links:category_index: '  + category_index  );

    if ( total_results_available < results_per_page ) return;

    if ( query_string ) {
        if ( query_string.match( /^javascript/ ) ) {
            // leave alone
        }
        else if ( query_string.match( /^\?/ ) ) {
            query_string += '&amp;s=$start';
        }
        else {
            query_string = '?s=$start';
        }
    }

    var max_displayable_pages = 20;

    var pages_available_count = Math.ceil(
        total_results_available / results_per_page
    );

    // Center the current page among the page links
    var first_page_number = Math.max(
        1,
        (
            current_page_number - ( max_displayable_pages / 2 )
        )
    );
    var last_page_number = Math.min(
        pages_available_count,
        (
            current_page_number + ( max_displayable_pages / 2 )
        )
    );

    var ul = new Array();

    // any page beyond the first page needs a previous link
    if ( current_page_number > 1 ) {
        ul.push( '<li>'
            // +     '&#91;'
            +     '<a href="'
            +         query_string.replace(
                          /\$start/,
                          ( start - results_per_page )
                      )
            +     '">'
            +         '&lt;&lt;'
            +     '</a>'
            // +     '&#93;'
            + '</li>'
        );
    }

    for (
        var page_number = first_page_number;
        page_number <= last_page_number;
        page_number++
    ) {
        page_start = ( ( page_number - 1 ) * results_per_page );

        if ( page_number == current_page_number ) {

            // current page is not a link
            ul.push(
                '<li>'
                // + '&#91;'
                + '&nbsp;' + page_number + '&nbsp;'
                // + '&#93;'
                + '</li>'
            );
        }
        else {

            // page links
            ul.push(
                '<li>'
                // + '&#91;'
                + '&nbsp;'
                + '<a href="'
                + query_string.replace( /\$start/, page_start )
                + '">' + page_number + '</a>'
                + '&nbsp;'
                // + '&#93;'
                + '</li>'
            );
        }
    }
    // More pages than the current page needs a next link
    if ( current_page_number < pages_available_count ) {
        ul.push( '<li>'
            // +     '&#91;'
            + '&nbsp;'
            +     '<a href="'
            +         query_string.replace(
                          /\$start/,
                          ( start + results_per_page )
                      )
            +     '">'
            +         '&gt;&gt;'
            +     '</a>'
            + '&nbsp;'
            // +     '&#93;'
            + '</li>'
        );
    }

    add_to_panels(
        '<ul id="page-links">' + ul.join( '' ) + '</ul>',
        [ 'page_links', 'page_links_top', 'page_links_bottom' ]
    );

    return;
}

function add_to_panels( html, ids ) {

    for ( var i in ids ) {

        var id = ids[i];

        var panel = domElement( id );

        if ( panel ) {
            panel.innerHTML = html;
        }
        else {
            logit( 'add_to_panels: unable to find \'' + id + '\' element' );
        }
    }
    return;
}

function start_spinner( rpc_class ) {

    // logit( 'start_spinner(\'' + rpc_class + '\');' );

    var rpc_spinner = domElement( 'rpc_spinner' );
    if ( !rpc_spinner ) {
        rpc_spinner = document.createElement( 'img' );
        rpc_spinner.src = 'img/wait.gif';
        rpc_spinner.height = '30';
        rpc_spinner.width = '30';
        rpc_spinner.setAttribute( 'id', 'rpc_spinner' );
        rpc_spinner.style.display = 'none';
        rpc_spinner.style.top = '-200px';
        rpc_spinner.style.left = '50%';
        rpc_spinner.style.position = 'fixed';
        rpc_spinner.style.visibility = 'visible';
        document.body.appendChild( rpc_spinner );
    }
    if ( rpc_spinner ) {
        rpc_spinner.style.top = '200px';
        rpc_spinner.style.display = 'block';
        // will attempt to stop in one second
        setTimeout( 'stop_spinner(\'' + rpc_class + '\')', 1000 );
    }
    return;
}

function stop_spinner( rpc_class ) {

    // logit(
    //     'stop_spinner(\'' + rpc_class + '\') for ['
    //         + window.current_rpc_id[ rpc_class ]
    //         + ']'
    // );

    // verify calling rpc is done
    if ( window.current_rpc_id[ rpc_class ] == null ) {

        var rpc_spinner = domElement( 'rpc_spinner' );
        if ( rpc_spinner ) {

            // turn off the spinner display
            rpc_spinner.style.display = 'none';

            logit( 'stop_spinner(\'' + rpc_class + '\') => stopped' );
        }
        else {
            // log failure to find the spinner dom element
            // logit(
            //   'stop_spinner(' + rpc_class + '): rpc_spinner doesn\'t exist'
            // );
        }
    }
    // if rpc is still working then procrastinate a second
    else {
        setTimeout('stop_spinner(\'' + rpc_class + '\');', 1000 );
    }
    return;
}

