var INPUT_REGEXP = new RegExp( "-input$" );
var TOOLTIP_DELAY = 500;
var dialogsQueue = new Array();


function getElementById( id ) {
    return document.getElementById( id );
}

function getElementsByTagName( name ) {
    return document.getElementsByTagName( name );
}

function removeChildNodes( node ) {
    var nodes = node.getElementsByTagName("*");
    for ( var i=0; i<nodes.length; i++ ) {
        node.removeChild(nodes[i]);
    }
}

function getEventTarget(event) {
    if ( typeof event == "undefined" ) event = window.event;
    
    var targetElement = null;

    if (typeof event.target != "undefined") {
        targetElement = event.target;
    } else {
        targetElement = event.srcElement;
    }

    while (targetElement.nodeType == 3 && targetElement.parentNode != null) {
        targetElement = targetElement.parentNode;
    }

    return targetElement;
}

function getViewportSize() {
    var size = [0, 0];

    if (typeof window.innerWidth != 'undefined') {
        size = [
            window.innerWidth,
            window.innerHeight
        ];
    } else if ( typeof document.documentElement != 'undefined' && 
                typeof document.documentElement.clientWidth != 'undefined' && 
                document.documentElement.clientWidth != 0 ) {
        size = [
            document.documentElement.clientWidth,
            document.documentElement.clientHeight
        ];
    } else {
        size = [
           document.getElementsByTagName('body')[0].clientWidth,
           document.getElementsByTagName('body')[0].clientHeight
        ];
    }

    return size;
}

function getScrollingPosition() {
    var position = [0, 0];

    if (typeof window.pageYOffset != 'undefined') {
        position = [
           window.pageXOffset,
           window.pageYOffset
        ];
    } else if (typeof document.documentElement.scrollTop != 'undefined' && document.documentElement.scrollTop > 0 ) {
        position = [
           document.documentElement.scrollLeft,
           document.documentElement.scrollTop
        ];
    } else if (typeof document.body.scrollTop != 'undefined') {
        position = [
           document.body.scrollLeft,
           document.body.scrollTop
        ];
    }

    return position;
}

function getElementsByClass( className ) {
    var elementArray = new Array();
    var matchedArray = new Array();

    if (document.all) {
        elementArray = document.all;
    } else {
        elementArray = document.getElementsByTagName("*");
    }

    var pattern = new RegExp("(^| )" + className + "( |$)");
    for ( var i=0; i<elementArray.length; i++ ) {
        if (pattern.test(elementArray[i].className)) {
            matchedArray[matchedArray.length] = elementArray[i];
        }
    }

    return matchedArray;
}

function getElementsWithMatchingID( id ) {
    var elementArray = new Array();
    var matchedArray = new Array();

    if (document.all) {
        elementArray = document.all;
    } else {
        elementArray = document.getElementsByTagName("*");
    }

    var pattern = new RegExp(id);
    for ( var i=0; i<elementArray.length; i++ ) {
        if (pattern.test( elementArray[i].id )) {
            matchedArray[matchedArray.length] = elementArray[i];
        }
    }

    return matchedArray;
}

function getFirstElementWithMatchingID( id ) {
    var elementArray = new Array();

    if (document.all) {
        elementArray = document.all;
    } else {
        elementArray = document.getElementsByTagName("*");
    }

    var pattern = new RegExp(id);
    for ( var i=0; i<elementArray.length; i++ ) {
        if (pattern.test( elementArray[i].id )) {
            return elementArray[i];
        }
    }

    return null;
}

function getCurrencyValue( id ) {
    var value = parseCurrency( getValue(id) );
    return isNaN(value) ? 0.0 : value; 
}

function getFloatValue( id ) {
    var value = parseFloat( getValue(id) );
    return isNaN(value) ? 0.0 : value; 
}

function getIntValue( id ) {
    var value = parseInt( getValue(id) );
    return isNaN(value) ? 0.0 : value; 
}

function getValue( id ) {
    var element = null;

    element = document.getElementById( id );
    if ( element ) {
        if ( typeof element.value != 'undefined'  ) {
            return element.value;
        } else {
            return element.innerHTML;
        }
    } 

    element = document.getElementById( id + "#V" );
    if ( element ) return element.innerHTML;

    element = getFirstElementWithMatchingID( id + "#V" );
    if ( element ) return element.innerHTML;

    element = document.getElementById( id + "-input" );
    if ( element ) {
        if ( typeof element.value != 'undefined'  ) {
            return element.value;
        } else {
            alert( "getValue(): Element with id \"" + id + "\" is not an input tag!" );
        }
    } else {
        alert( "getValue(): Element with id \"" + id + "\" does not exist!" );        
    }
    
    return null;
}

function setValue( id, value ) {
    var element = document.getElementById( id );
    if ( element ) {
        if ( typeof element.value != 'undefined'  ) {
            element.value = value;
        } else {
            element.innerHTML = value;
        }
    } 

    var elements = getElementsWithMatchingID( id+"#V" );
    if ( elements.length == 0 && element == null ) {
        alert( "setValue(): Element with id \"" + id + "\" does not exist!" );    
        return;
    }
    for ( var i=0; i<elements.length; i++ ) {
        elements[i].innerHTML = value;
    }
}


//***********************************************************
//***************** FORMATTING FUNCTIONS ********************
//***********************************************************
function parseCurrency(s) {
    s = s.replace( "\u20ac", "" ).replace( / /g, "" ).replace( /,/g, "" ).replace(/&nbsp;/g, "" );
    return parseFloat(s);
}

function toCurrency( value ) {
    value = formatNumber( value, 2 );
    if ( value.indexOf("-") == 0 ) {
        value = "-&nbsp;&euro;" + value.substring(1);
    } else {
        value = "&euro;" + value;
    }
    return value;
}

function writeCurrency( value ) {
    document.write( toCurrency(value) );
}

function toInteger( value ) {
    return formatNumber( value, 0 );
}

function writeInteger( value ) {
    document.write( toInteger( value ) );
}

function toTime( value ) {
    var min = Math.floor(value/60);
    var sec = value%60;
    if ( sec < 10 ) sec = "0" + sec;
    if ( min < 10 ) min = "0" + min;
    return min + ":" + sec;
}

function writeTime( value ) {
    document.write( toTime(value) );
}

function toTons( value ) {
    value = formatNumber( value, 0 );
    return value+"t";
}

function writeTons( value ) {
    document.write( toTons(value) );
}

function toPercent( value ) {
    value = value.toFixed(2);
    return value+"%";
}

function writePercent( value ) {
    document.write( toPercent(value) );
}

function formatNumber( value, fixed ) {
    if ( typeof value == 'string' ) value = parseFloat( value );
    
    var negative = value < 0.0;
    value = Math.abs( value );
    value = value.toFixed( fixed ).toString();

    var n = 3 + ((fixed>0) ? 1+fixed : 0);
    while (value.length > n) {
        value = value.substring(0,value.length-n) + "," + value.substring(value.length-n);
        n += 4;
    }
    
    if ( negative ) value = "-" + value;
    
    return value;
}

function toValueID( id ) {
    return id.substring(0, id.indexOf("#"));
}


/******************************************************
 ********** SERVER CONNECTION FUNCTIONS ***************
 ******************************************************/
function invokeRemoteAction() {
    if ( arguments.length ) {
        switch (arguments.length) {
            case 1:
                invokeRemoteActionFull( "GET", arguments[0], null, null, null );
                break;
            case 2:
                invokeRemoteActionFull( "GET", arguments[0], null, arguments[1], null );
                break;
            case 3:
                invokeRemoteActionFull( "GET", arguments[0], null, arguments[1], arguments[2] );
                break;
            case 4:
                invokeRemoteActionFull( "POST", arguments[0], arguments[1], arguments[2], arguments[3] );
                break;
            default:
                alert( "Bad number of arguments passed to 'invokeRemoteAction()'!" );
                break;
        }
    }
}

function invokeRemoteActionFull( method, action, args, callback, errorHandler ) {
    var xhr = createXMLHttpRequest();
    xhr.onreadystatechange = function() {        
        if ( xhr.readyState == 4 ) {
            if ( xhr.status ) { 
                if ( xhr.status == 200 ) {
                    if ( callback ) callback( xhr.responseText );
                } else {
                    if ( errorHandler ) errorHandler( xhr.status, xhr.responseText );
                }
            }
        }
    }
    xhr.open( method, action, true );
    xhr.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2005 00:00:00 GMT" );
    xhr.send( args );
}

function createXMLHttpRequest() {
    try {
        // Firefox, Opera 8.0+, Safari
        return new XMLHttpRequest();
    } catch (e) {
        // Internet Explorer
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                return new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                alert("Your browser does not support AJAX!");
                return null;
            }
        }
    }
}


/******************************************************
 *************** DIALOG FUNCTIONS *********************
 ******************************************************/
function showDialogFromQueue() {
    if ( dialogsQueue.length > 0 ) {
        showDialog( dialogsQueue.shift() );
    } else {
        closeCurrentDialog();
    }
    return false;
}

function dialogsInQueue() {
    return dialogsQueue.length > 0;
}

function showDialog(id) {
    var dialogContainer = getElementById("dialogs-container");
    var dialog = dialogContainer.firstChild;
    
    if ( dialog != null ) {
        dialogContainer.style.visibility = "hidden";
        dialogContainer.removeChild( dialog );
        getElementById("dialogs").appendChild( dialog );
    }

    var overlay = getElementsByClass("overlay")[0];
    var viewportSize = getViewportSize();
    var scrollingPosition = getScrollingPosition();
    
    var pageTag = getElementsByClass("page")[0];    
    overlay.style.height = (pageTag.clientHeight+pageTag.offsetTop) + "px";
    
    if ( document.getElementById(id) ) {
        dialogContainer.appendChild( document.getElementById(id) );
        dialogContainer.style.left = (viewportSize[0]-dialogContainer.offsetWidth)/2 + "px";
        dialogContainer.style.top = scrollingPosition[1]+(viewportSize[1]-dialogContainer.offsetHeight)/2 + "px";    
        overlay.style.display = "block";
        dialogContainer.style.visibility = "visible";
    } else {
        overlay.style.display = "none";
        dialogContainer.style.visibility = "hidden";
        alert( "Unknown dialog Id: " + id );
    }
}

function closeCurrentDialog() {
    var dialogContainer = getElementById("dialogs-container");
    var dialog = dialogContainer.firstChild;
    if ( dialog != null ) {
        dialogContainer.style.visibility = "hidden";
        dialogContainer.removeChild( dialog );
        getElementById("dialogs").appendChild( dialog );
    }
    var overlay = getElementsByClass("overlay")[0];
    overlay.style.display = "none";
    return false;
}

function addDialogToQueue( id ) {
    dialogsQueue.push(id);
}

function clearDialogsQueue() {
    dialogsQueue.length = 0;
}

function addOkButtonsToDialogs( dialogs ) {
    var bottomPanel, button;
    for ( var i=0; i<dialogs.length; i++ ) {
        if ( dialogs[i].getElementsByTagName("div").length > 0 ) continue;
        button = createButton( "ok", null, showDialogFromQueue );
        bottomPanel = document.createElement("div");
        bottomPanel.className = "bottomPanel";
        bottomPanel.appendChild( button );
        dialogs[i].appendChild( bottomPanel );
    }
}


/******************************************************
 *************** TOOLTIP FUNCTIONS ********************
 ******************************************************/
 function setupTooltips() {
    var tips = getElementsByClass("hastooltip");
    for ( var i=0; i<tips.length; i++ ) {
        tips[i].onmouseover = showTip;
        tips[i].onmouseout = hideTip;
    }
}

function showTip(event) {
    if ( typeof event == "undefined" ) event = window.event;
    var target = getEventTarget(event);

    while (target.className == null || !/(^| )hastooltip( |$)/.test(target.className)) {
        target = target.parentNode;
    }

    var textID = target.getAttribute("id");
    var index = textID.indexOf("#");
    if ( index > -1 ) {
        textID = textID.substring(0, index);
    } 
    
    var tip = document.createElement("div");
    var content = document.getElementById( "tooltip-" + textID ).innerHTML;   

    target.tooltip = tip;
    target.setAttribute("title", "");

    tip.className = "tooltip";
    tip.innerHTML = content;

    var scrollingPosition = getScrollingPosition();
    var cursorPosition = [0, 0];

    if (typeof event.pageX != "undefined" && typeof event.x != "undefined") {
        cursorPosition[0] = event.pageX;
        cursorPosition[1] = event.pageY;
    } else {
        cursorPosition[0] = event.clientX + scrollingPosition[0];
        cursorPosition[1] = event.clientY + scrollingPosition[1];
    }

    tip.style.position = "absolute";
    tip.style.left = cursorPosition[0] + 10 + "px";
    tip.style.top = cursorPosition[1] + 10 + "px";
    tip.style.visibility = "hidden";

    document.getElementsByTagName("body")[0].appendChild(tip);

    var viewportSize = getViewportSize();

    if (cursorPosition[0] - scrollingPosition[0] + 10 + tip.offsetWidth > viewportSize[0] - 25) {
        tip.style.left = scrollingPosition[0] + viewportSize[0] - 25 - tip.offsetWidth + "px";
    } else {
        tip.style.left = cursorPosition[0] + 10 + "px";
    }

    if (cursorPosition[1] - scrollingPosition[1] + 10 + tip.offsetHeight > viewportSize[1] - 25) {
        if (event.clientX > (viewportSize[0] - 25 - tip.offsetWidth)) {
            tip.style.top = cursorPosition[1] - tip.offsetHeight - 10 + "px";
        } else {
            tip.style.top = scrollingPosition[1] + viewportSize[1] - 25 - tip.offsetHeight + "px";
        }
    } else {
        tip.style.top = cursorPosition[1] + 10 + "px";
    }
    
    setTimeout( function() { tip.style.visibility = "visible"; }, TOOLTIP_DELAY );

    return true;
}

function hideTip(event) {
    if ( typeof event == "undefined" ) event = window.event;

    var target = getEventTarget(event);

    while (target.className == null || !/(^| )hastooltip( |$)/.test(target.className)) {
        target = target.parentNode;
    }

    if ( target.tooltip != null ) {
        target.setAttribute("title", target.tooltip.childNodes[0].nodeValue);
        target.tooltip.parentNode.removeChild(target.tooltip);
    }

    return false;
}


//***************************************************
//************ UTILITY FUNCTIONS ********************
//***************************************************
function createButton( textId, buttonId, callback ) {
    var button = document.createElement("a");
    button.className = "button";
    button.id = buttonId;
    button.href = "";
    button.onclick = callback;
    button.innerHTML = getElementById( textId ).innerHTML;
    return button;
}


