/// debug dump
function debug( obj ){
    alert( debug_build( obj, 0 ) );
}
function debug_build( obj, idx ){
    var space = "";
    for( var i = 0; i < idx; i++ ){
        space += "    ";
    }
    if( typeof( obj ) == "object" ){
        var string = "";
        for( var i in obj ){
            string += space + i + ":\n";
            string += space + debug_build( obj[i], idx + 1 ) + "\n";
        }
        return string;
    }else{
        return space + obj;
    }
}


/// eval the text, if faied return the default failure message
function my_eval( data ){
    try{
        var o = eval( "(" + data + ")" );
        return o;
    }catch( e ){
        return { response: 0, msg: "Oops, seems something wrong with the server. Please refresh this page and try again.", data: [] };
    }
}


/// Refresh current page
function refresh(){
    window.location.reload();
}

/// Show/Hide the cover
function page_cover( on, idx ){
    idx = idx || 10;
    var c = $( ids.page_cover );
    on ? c.css( "width", $(document).width() ).css( "height", $(document).height() ).css( "z-index", idx ).show() : c.hide();
}

/// Show/Hide the loading gif
function loading( on, txt ){
    var l = $( ids.loading );
    if( !txt && on ){
        txt = "Loading...";
    }
    $( ids.loading + ">div" ).next().html( txt );
    on ? l.css( "margin-left", - l.width() / 2 ).stop().show() : l.fadeOut( "medium" );
}


/// Show/Hide the popup window
var popup = {

    close_disabled: false,
    showing: false,
    attached: false,

    working: function( on, txt ){
        this.close_disabled = on || false;
        loading( on, txt );
    },

    /// set the html of the popup but don't show it. so you can manpulate the DOM before show the popup, or replace the popup content
    set: function( html ){
        if( typeof html == "string" ){
            $( ids.popup_content ).html( html );
        }else{
            $( ids.popup_content ).empty().append( html );
        }
    },

    show: function( html, top ){
        this.showing = true;
        var o = $( ids.popup );
        html && $( ids.popup_content ).html( html );
        top = $(document).scrollTop() + ( top || ( o.height() > 500 ? 1 : 50 ) );
        o.css( "margin-left", - o.width() / 2 ).css( "top", top ).show();
        if( !this.attached ){
            this.attach();
        }
        page_cover( 1 );
    },

    hide: function(){
        this.close();
    },

    close: function(){
        if( !this.close_disabled ){
            this.showing = false;
            $( ids.popup ).hide( "fast" );
            page_cover();
        }
    },
    attach: function(){
        $( ids.popup ).keypress( function (e){ e.keyCode == 27 ? popup.close() :"" } ); // dosen't work under Chrome
    }
}


/// read a innerHTML of an element and clean it
function get_inner( id, rm ){
    var html = $( id ).html();
    rm && $( id ).remove();
    return html;
}

/// get all the input into an object and return it
function get_inputs( id ){
    var values = {};

    // all the <input>
    var ip = $( id + " input" ).get();
    for( i = 0; i < ip.length; i++ ){
        if( ip[i].type == "radio" ){
            ip[i].checked ? values[ip[i].name] = ip[i].value : "";
        }else if( ip[i].type == "checkbox" ){
            ip[i].checked ? values[ip[i].name] = ip[i].value : "";
        }else{
            values[ip[i].name] = ip[i].value;
        }
    }
    // all the <select>
    ip = $( id + " select" ).get();
    for( i = 0; i < ip.length; i++ ){
        values[ip[i].name] = ip[i].selectedIndex == "-1" ? "" : ip[i].options[ip[i].selectedIndex].value;
    }
    // all the <textarea>
    ip = $( id + " textarea" ).get();
    for( i = 0; i < ip.length; i++ ){
        values[ip[i].name] = ip[i].value;
    }

    return values;
}

/// set the inputs
function set_inputs( fid, names, vals, f_name ){
    var o = $(fid);
    if( o ){
        for( var i = 0; i < names.length; i++ ){
            o.find( "[name='" +names[i]+ "']" ).val( ( vals[i] ? vals[i] : "" ) );
        }
        f_name && o.find( "[name='" +f_name+ "']" ).focus();
    }
}


/// easy function for mouse hover class change
function m_over(){
    $(this).addClass( "over" );
}
function m_out(){
    $(this).removeClass( "over" );
}


/// same as the floatvar in PHP
function floatval( v ){
    return parseFloat( v ) || 0;
}

/// round to 2 decimal for money display
function money( n, f ){
    n = ( Math.round( n * 100 ) / 100 ).toString();
    var i = n.indexOf( "." );
    if( i == -1 ){
        n += ".00";
    }else if( i == n.length - 2 ){
         n += "0";
    }
    return f ? n : '$' + to_numstr( n );
}
/// add , to numbers
function to_numstr( n ){
    var t = Math.floor( ( n.length - 3 ) / 3 );
    if( ( n.length - 3 ) % 3 == 0 ){
        t--;
    }
    for( i = t; i > 0; i-- ){
        var m = n.length - 3 - i * 3;
        n = n.substring( 0, m ) + "," + n.substring( m );
    }
    return n;
}
/// add leading 0 to numbers
function prepend0( n, d ){
    n = n + "";
    d = d || 2;
    for( var i = n.length; i <d; i++ ){
        n = '0' + n;
    }
    return n;
}

/// cut down the string into a certain length
function cut_down( str, num ){
    return str ? str.substring( 0, num ) + ( str.length > num ? "..." : "&nbsp;" ) : "";
}

/// put all the keys in this object in an array
function obj_keys( obj ){
    var a = [];
    for( var i in obj ){
        a[a.length] = i;
    }
    return a;
}

/// turn an object into an array
function obj_to_arr( obj ){
    var a = [];
    for( var i in obj ){
        a[a.length] = obj[i];
    }
    return a;
}

/// sort an array of objects
function obj_sort( arr, key ){
    arr.sort(
        function( a, b ){
            var ak = a[key].toUpperCase();
            var bk = b[key].toUpperCase();
            if( ak < bk ) return -1
            if( ak > bk ) return 1
            return 0
        }
    );
    return arr;
}

/// make every element in this array unique
function array_unique( arr ){
    var a = [];
    for( var i = 0; i < arr.length; i++ ){
        if( $.inArray( arr[i], a ) == -1 ){
            a[a.length] = i;
        }
    }
    return a;
}

/// turn line breaks to <br />
function nl2br( str ){
    return (str + '').replace(/([^>]?)\n/g, '$1<br />\n');
}

/// turn timestamp to a string date
function to_time( t, without_time ){
    if( test( t ) ){
        var d = new Date( t * 1000 );
        return d.getFullYear() + "-" + prepend0( d.getMonth() + 1 ) + "-" + prepend0( d.getDate() ) + ( without_time ? "" : " " + prepend0( d.getHours() ) + ":" + prepend0( d.getMinutes() ) ) ;
    }
    return "";
}

/// the tabs object
function tabs( id, funcs ){
    this.id = id;
    this.obj = null;
    this.tab_caps = [];
    this.tabs = [];
    this.funcs = funcs || [];

    /// tab click event
    this.select = function( e, d ){
        d ? d.tab_obj.show( d.id ) : this.tab_obj.show( this.id );
    }

    /// switch to the tab
    this.show = function( id ){
        for( var i = 0; i < this.tab_caps.length; i++ ){
            if( this.tab_caps[i].id == id ){
                $( this.tab_caps[i] ).addClass( "cur" );
                this.tabs.eq(i).show();
                if( this.funcs[i] ){
                    this.funcs[i]();
                }
            }else{
                $( this.tab_caps[i] ).removeClass( "cur" );
                this.tabs.eq(i).hide();
            }
        }
    }

    /// get all the tab elements and add the events
    this.init = function( idx ){
        idx = idx || 0;
        this.obj = $( this.id );
        /*
        this.tab_caps = this.obj.find( ".caps>div" ).click( this.select ).get();
        this.tabs = this.obj.find( ".tab" );
        */
        this.tab_caps = this.obj.children( ".caps" ).children( "div" ).hover( m_over, m_out ).click( this.select ).get();
        this.tabs = this.obj.children( ".tab" );
        for( var i = 0; i < this.tab_caps.length; i++ ){
            this.tab_caps[i].tab_obj = this;
            this.tab_caps[i].id = this.id + "_" + i;
        }
        this.select( null, this.tab_caps[idx] );
    }

    // init the tabs
    this.init();
}


/// type prompt, no need to be an object since there should only be one pmpt on the screen
var pmpt = {

    showing: "",
    e: "",
    over: 0,

    get_id: function( e ){
        return e.name + "_" + e.id;
    },

    get_div: function( e ){
        var o = new jQuery( '<div id="' +this.get_id(e)+ '" class="prmpt" />' );
        o.width( $(e).width() + 2 );
        if( $.browser.msie ){
            o.width( $(e).width() + 4 );
            o.addClass( "prmpt-iefix" );
        }
        return o;
    },

    show: function( e, values ){
        values = values || this.pmpt_values || [];
        if( values && values.length ){
            var id = pmpt.get_id( this );
            if( id != pmpt.showing ){
                pmpt.hide();
                var o = pmpt.get_div( this );
                $(this).before( o );
            }else{
                var o = $( "#" + pmpt.showing );
            }
            pmpt.showing = id;
            pmpt.e = this;
            o.empty();
            for( var i = 0; i < values.length; i++ ){
                o.append( '<div>' + values[i] + '</div>' );
            }
            o.children( "div" ).hover( pmpt.m_over, pmpt.m_out ).click( pmpt.click );
        }
    },

    hide: function( e, c ){
        if( pmpt.showing && ( c || !pmpt.over ) ){
            $( "#" + pmpt.showing).remove();
            pmpt.showing = "";
            pmpt.e = "";
            pmpt.over = 0;
        }
    },

    m_over: function( e ){
        pmpt.over = 1;
        $(this).addClass( "over" );
    },
    m_out: function( e ){
        pmpt.over = 0;
        $(this).removeClass( "over" );
    },
    click: function( e ){
        if( pmpt.e ){
            $(pmpt.e).val( $(this).text() );
            //pmpt.e.focus();
            pmpt.hide( 0, 1 );
        }
    },

    init: function( elem, vs ){
        if( elem.get().length ){
            elem.get(0).pmpt_values = vs || [];
            elem.focus( pmpt.show ).blur( pmpt.hide );
        }
    }
};


/// functions for ajax requests
var req = {
    // pop up the interface
    popup: function( tmpl, focus_id ){
        popup.show( tmpl );
        focus_id && $( focus_id ).focus();
    },
    // post the request
    submit: function( url, inputs, callback, fid, is_pop ){
        fid && $( fid + " input[type='submit']" ).attr( "disabled", 1 );
        $.post( url, inputs, callback );
        is_pop && popup.working(1);
    },
    // post call back, eval the reply
    callback: function( msg, fid, is_pop ){
        fid && $( fid + " input[type='submit']" ).attr( "disabled", 0 );
        is_pop && popup.working();
        return my_eval( msg );
    }
};


/// add a 'err' class to the input fields that appear as a key in the array
function set_err_inputs( fid, errs ){
    var o = $(fid);
    if( o ){
        for( var k in errs ){
            o.find( "[name='" +k+ "']" ).addClass( "err" );
        }
    }
}
/// remove all the 'err' class in a form
function unset_err_inputs( fid ){
    $(fid + " *").removeClass( "err" );
}


/// trim
function trim( txt ){
    return txt.replace( /^\s+|\s+$/g, "" );
}


/// trim some text to valid URL
function trim_url( txt ){
    return txt.toLowerCase().replace( /\s/g, "_" ).replace( /[^a-z0-9_]/g, "" ).replace( /^_+|_+$/g, "" );
}


/// return true for none 0 or "0"
function test( v ){
    return ( v && v != 0 && v != "0" );
}


/// return the content of a frame
function get_frm_html( id ){
    var e = document.getElementById( id.replace( /^#/, "" ) );
    var d = "";
    if( e.contentDocument ){
        d = e.contentDocument;
    }else if( e.contentWindow ){
        d = e.contentWindow.document;
    }else if( window.frames[id] ){
        d = window.frames[id].document;
    }
    if( d ){
        //return $.browser.msie ? d.body.innerText : d.body.textContent;
        return d.body.innerHTML;
    }
}


/// pop up a small window
function pop( id, url, w, h, l, t ){
    id = id || "_blank";
    w = w || 400;
    h = h || 420;
    l = l || 200;
    t = t || 100;
    win = window.open( url, id, 'width=' +w+ ',height=' +h+ ',left=' +l+ ',top=' +t+ ',scrollbars=auto,menubar=no,resizable=yes' );
    win.top.focus();
}


// count down
$.fn.CountDown = function( opt ){
    if( !opt ){
        return false;
    }
    if( $( this ).length == 0 ){
        return false;
    }
    var obj = this;
    opt.style = opt.style || "str";

    if( !opt.d || opt.d < 1 ){
        opt.d = 2 ;
    }
    // callback when reach 0
    if( opt.s < 0 ){
        if( opt.callback ){
            eval( opt.callback );
        }
        return null;
    }
    // set the timer to 1000ms
    window.setTimeout(
        function() {
            opt.s -= 1 ;
            if( opt.s > 0 || opt.m > 0 || opt.h > 0 ){
                if( opt.s < 0 ) {
                    opt.s = 59;
                    opt.m -= 1;
                    if( opt.m < 0 ) {
                        opt.m = 59;
                        opt.h -= 1;
                        if( opt.h < 0 ) {
                            opt.h = 23;
                        }
                    }
                }
            }
            $( obj ).CountDown( opt );
        },
        1000
    );

    if( opt.style != "str" ){
        $( obj ).html( opt.style( opt.h, opt.m, opt.s ) );
    }else{
        $( obj ).html( prepend0( opt.h, opt.d ) + ':' + prepend0( opt.m, opt.d ) + ':' + prepend0( opt.s, opt.d ) );
    }

    return this;
}


// input text hints replacement
function input_hints( id, v ){
    $( id ).focus(
        function(){
            if( $(this).val() == v ) $(this).val( "" );
        }
    ).blur(
        function(){
            if( $(this).val() == "" ) $(this).val( v );
        }
    );
}


// check if enter is pressed
function is_enter( e ){
    if( e ){
        var k = (e.keyCode) ? e.keyCode : e.which;
        return ( k == 13 );
    }
    return false;
}