// Pings the server regularly to ensure the user http session stays alive.
// Also updates a "status bar" in the current window to show the user that the
// server is alive (changes colour of a small box, etc).
//
// If the server stops replying to pings, then a popup alert box is shown and the current window
// is then redirected to a "connection lost" page (which is typically the login page of the app).
//
// As OPSJ webapps are set up to only allow one request at a time for a user, it is necessary to
// disable the pinging when the user triggers a page submit (whether a link or a submit button).
// Without this, ping requests will queue up behind the request triggered by the user. If the new
// page takes too long to generate then the javascript here will think the server is down and
// redirect to the "connection lost" page. This disabling is done by scanning the page for forms
// and links, and modifying their onsubmit or onclick callbacks to set the pingBlockDuringPost flag.
// Nothing ever sets this flag back to false; the new page simply has a fresh copy of the variable. 
// 
// There is an added complication when a page includes an IFrame. Components in the iframe
// don't contain a copy of the ping script; that would be attached to the child window within
// the frame and that causes complications. But links and submit buttons in the iframe should
// cause the "global" pingBlockDuringPost to be set. However when the iframe contents is replaced
// by a new page, this will *not* reset the global pingBlockDuringPost variable.   
//
// The "status bar" within the page must have an id of "sesTO". It might be an iframe widget,
// in which case a GET is used to ping the server and the contents is inserted into the iframe.
// Or it might just be a plain div, in which case an ajax request is used to ping the server,
// and the div contents are replaced with the ajax response content. 
// 
// Every page in an OPSJ webapp is expected to include this script, and to call
// ping_init after the page is loaded.

var sesTO = null;
var pingBodyLost = 0;
var pingUrl = null;

var pingIntervall = 0;

var pingWatchdog = 0;
var pingCounter = 0;

var pingLastCounter = 0;

var pingBlockDuringPost = false;

// Handle case where the "status bar" is a plain div; use AJAX to ping the server.
function ping_SesTOTimer()
{
    // watchdog
	if (pingWatchdog > 3 && !pingBlockDuringPost)
	{
		pingBodyLost++;
		if (pingBodyLost > 1)
		{
			alert("Verbindung zum Server wurde unterbrochen.");
			if (window.pingConnectionLostUrl)
			{
				window.location.replace(window.pingConnectionLostUrl);
			}
			return;
		}
	}
	else
	{
		pingBodyLost = 0;
	}

	var ping = pingUrl;
	if (ping.indexOf("?") > -1)
	{
		ping += "&";
	}
	else
	{
		ping += "?";
	}
	ping += "COUNT=" + pingCounter;

	// sesTO.location.replace(ping);


	if (!pingBlockDuringPost)
	{
		// Send off the ping request to the server, and have the nested function invoked
		// when (if) a response is received from the server.
		//
		// If the browser does not support Ajax, then this method will throw an exception
		// which we deliberately do not catch. The timer therefore will not be reset, and
		// so pinging is simply disabled.
		//
		// Note the the callback function gets called even when the server is down; it
		// therefore must check whether the result really was successful. The xmlHttp.status
		// field is the proper way to check for this, but it appears that at least some versions
		// of IE don't set this correctly so here we check for presence of responseXML instead.
		opsjExecuteAjax(ping, function (xmlHttp)
			{
				if (xmlHttp.responseXML)
				{
					pingWatchdog=0;

                    var color = xmlHttp.responseXML.getElementsByTagName("progressColor")
					if (typeof sesTO != "undefined" && color && color.length && color.length > 0)
					{
						sesTO.style.backgroundColor=color[0].getAttribute("color");
					}

					var messages = xmlHttp.responseXML.getElementsByTagName("messages")
					if (messages && messages.length && messages.length > 0)
					{
						var messageAvailable = messages[0].getAttribute("available");
						if (messageAvailable == "false")
						{
							od_setHide(od_g(document, "mailboxFullIndicator"), true);
							od_setHide(od_g(document, "mailboxEmptyIndicator"), false);
						}
						else
						{
							od_setHide(od_g(document, "mailboxFullIndicator"), false);
							od_setHide(od_g(document, "mailboxEmptyIndicator"), true);

							if (messageAvailable == "critical")
							{
							}
						}
					}
				}
			}, true);

		pingWatchdog++;
		pingCounter++;
	}

	setTimeout("ping_SesTOTimer()", pingIntervall);
}

// Handle case where the "status bar" is an iframe; use GET to ping the server.
function ping_SesTOTimerIframe()
{
	if (isInPageChange())
	{
		return;
	}

	// watchdog
	if (pingCounter - pingLastCounter > 1)
	{
		pingBodyLost++;
		if (pingBodyLost > 1)
		{
			alert("Verbindung zum Server wurde unterbrochen.");
			if (window.pingConnectionLostUrl)
			{
				window.location.replace(window.pingConnectionLostUrl);
			}
			return;
		}
	}
	else
	{
		pingBodyLost=0;
	}

	if (pingCounter > 0)
	{
		var ping;
		if (pingUrl.indexOf("?") > -1)
		{
			ping = pingUrl + "&COUNT=" + pingCounter;
		}
		else
		{
			ping = pingUrl + "?COUNT=" + pingCounter;
		}

		if (sesTO)
		{
			if (sesTO.contentWindow)
			{
				sesTO.contentWindow.location.replace(ping);
			}
			else
			{
				sesTO.location.replace(ping);
			}
		}
	}

	pingCounter++;

	setTimeout("ping_SesTOTimerIframe()", pingIntervall);
}

// Walk the entire document installing hooks for form.onsubmit and
// link.onclick so that we can stop pinging when a server request
// has been sent.
function ping_registerOnSubmitInterceptor()
{
    for (var i = 0; i < document.forms.length; i++)
    {
        var form = document.forms[i];

        ping_registerEventInterceptor(form, form.onsubmit, "onsubmit");
    }

    for (var i = 0; i < document.links.length; i++)
    {
        var link = document.links[i];

        ping_registerEventInterceptor(link, link.onclick, "onclick");
    }
}

// Install onsubmit or onclick  hook for the specified element.
// See docs for ping_registerOnSubmitInterceptor.
function ping_registerEventInterceptor(element, origOnevent, event)
{
    if (element.opsjPingHookInstalled)
    {
      // we have already processed this element
      return;
    }

    element.opsjPingHookInstalled = true;
    element[event] = function(event)
    {
        if (!event) event = window.event;

        if(null != origOnevent && typeof origOnevent != "undefined")
        {
            var doEvent;
            if (typeof origOnevent == "string")
            {
                doEvent = eval(origOnevent);
            }
            else if (origOnevent.call)
            {
                doEvent = origOnevent.call(element, event);
            }
            else
            {
                doEvent = origOnevent();
            }
           if(doEvent || typeof doEvent == "undefined")
           {
               pingBlockDuringPost = true;
               return true;
           }
           return false;
        }
        else
        {
            pingBlockDuringPost = true;
            return true;
        }
    }
}

// Function that must be called immediately after page load to start
// pinging of the server.
function ping_init(pingConnectionLostUrlArg, pingUrlArg, pingIntervallArg)
{
	window.pingConnectionLostUrl = pingConnectionLostUrlArg;
	pingUrl = pingUrlArg;
	pingIntervall = pingIntervallArg;

    // get the "status bar" node.
	sesTO = document.getElementById("sesTO");
	if (sesTO != null)
	{
        // Walk the entire document installing hooks
		ping_registerOnSubmitInterceptor();

		// Cause first ping request to be sent.
		if (sesTO.nodeName && sesTO.nodeName.toLowerCase() == "iframe")
		{
			ping_SesTOTimerIframe();
		}
		else
		{
			ping_SesTOTimer();
		}
	}
}
