var HEALTH = {
  SESSIONHEALTHY: "health:sessionhealthy",
  SESSIONFAILURE: "health:sessionfailure",
  NETWORKFAILURE: "health:networkfailure",
  PERMANENTNETWORKFAILURE: "health:permanentnetworkfailure",
  TIMEOUT: 30, // seconds
  CONNECTIONFAILUREMAX: 5 // failure count
}

Event.observe(window, "load", OnLoadKMMagmaHealth);  

function OnLoadKMMagmaHealth()
{    
  if ((self.MAGMA) && (MAGMA.EVENT)) {
    MAGMA.EVENT.HEALTH = HEALTH;
  }  
}
 
function KMMagmaHealth(sid, url, eventSink)
{
  var _sid = sid;
  var _url = url;
  var _eventSink = eventSink;
  var _pe = null;    
  var _connectionFailureCount = 0;  
  
  this.Start = _Start;
  this.Stop = _Stop;
  this.Sid = _sid;
  this.Url = _url;
  this.EventSink = _eventSink;
  
  function _Start()
  {            
    _connectionFailureCount = 0;
    _pe = new PeriodicalExecuter(
      function() {
        _Check();
      }, HEALTH.TIMEOUT);
  } 
  
  function _Stop()
  {
    if (_pe != null) {
      _pe.stop();
    }
  }
  
  function _FireEvent(event)
  {
    if ((event != null) && (event !== "")) {
      if (_eventSink != null) {
        Event.fire(_eventSink, event);
      } else if ((self.Proxy) && (Proxy.GetEventSink() != null)) {
        Proxy.GetEventSink().fire(event);
      }
    }  
  }  

  function _Check()  
  {
    if ((_sid == null) || (_url == null)) { 
      _Stop();
    } else {    
      var list = new Hash({ "sid": _sid, "magma": "session.query" });	
      	  
      try { 
      	new Ajax.Request(_url,
      	{
      	  method: 'get',
          evalJSON: true,
      		parameters: list.toQueryString(),
      		onSuccess: _CheckSuccess,			
      	  onFailure: function() {			  	  				    	
      	  	_NetworkFailure();
      	  }
      	});		  
      } catch(ex) {
        _NetworkFailure();
      }    
    }
  }
  
  function _CheckSuccess(result)
  {
    try {
      if ((result == null) || (result.responseJSON == null)) {
        _NetworkFailure();  
      } else if (!result.responseJSON.Active) {
        _CheckFailure();
      } else if (_connectionFailureCount > 0) {
        _connectionFailureCount = 0;
        _FireEvent(HEALTH.SESSIONHEALTHY);      
      }
    } catch(ex) {
      _NetworkFailure();
    }        
  }
  
  function _CheckFailure()
  {    
    _Stop();    
    _FireEvent(HEALTH.SESSIONFAILURE);
  }
  
  function _NetworkFailure()
  {    
    _connectionFailureCount++;
    if (_connectionFailureCount == 1) {
      _FireEvent(HEALTH.NETWORKFAILURE);
    }
    
    if (_connectionFailureCount >= HEALTH.CONNECTIONFAILUREMAX) {
      _Stop();
      _FireEvent(HEALTH.PERMANENTNETWORKFAILURE);
    }          
  }
}

function KMMagmaHealthUI(options)
{   
  var _options = options; 
  
  _Initialize();  
  
  function _Initialize()
  {
    if (_options) {
      for (var key in _options) {
        if (typeof _options[key] == "string") {          
          _options[key] = $(_options[key]);
        }
      }    
      
      if ((Object.isElement(_options.DivNetworkFailure)) && 
          (Object.isElement(_options.DivPermanentNetworkFailure)) &&
          (Object.isElement(_options.DivSessionFailure)) &&
          (Object.isElement(_options.DivPanel))) {       
        Element.hide(_options.DivNetworkFailure);
        Element.hide(_options.DivPermanentNetworkFailure);
        Element.hide(_options.DivSessionFailure);            

        if (typeof _options.Dialog != "object") {
          _options.Dialog = new Knowmax.SimpleDialog.Add({Element: _options.DivPanel,
            Modal: true, ModalShowDuration: 2.0});                        
        }
      
        var sink = _options.EventSink;
        if ((sink == null) && (self.Proxy) && (Proxy.GetEventSink() != null)) {
          sink = Proxy.GetEventSink();
        }    
        
        if (sink == null) {
          sink = document;
        }
        
        sink.observe(HEALTH.NETWORKFAILURE, _OnNetworkFailure);
        sink.observe(HEALTH.SESSIONFAILURE, _OnSessionFailure);
        sink.observe(HEALTH.SESSIONHEALTHY, _OnSessionHealthy);  
        sink.observe(HEALTH.PERMANENTNETWORKFAILURE, _OnPermanentNetworkFailure);        
      }
    }
  }  
  
  function _OnNetworkFailure()
  {            
    Element.show(_options.DivNetworkFailure);
    _options.Dialog.Show();  
  }
  
  function _OnSessionFailure()
  {            
    Element.show(_options.DivSessionFailure);
    _options.Dialog.Show();   
  }
  
  function _OnSessionHealthy()
  {          
    _options.Dialog.Hide();
    Element.hide(_options.DivNetworkFailure);
  }
  
  function _OnPermanentNetworkFailure()
  {    
    Element.hide(_options.DivNetworkFailure);
    Element.show(_options.DivPermanentNetworkFailure);    
  }
}