var DataChangeWatcher;

(function() {

  if (DataChangeWatcher == null)
  {
    DataChangeWatcher = new Object();
    var validationGroup = "DataChangeWatcherValidationGroup";
    var warningMessage = "Cancel your changes?";
    var watch = false;
    var isInited = false;
    var savedValues = new Object();
    var debugDCW = false;
    var alreadyChanged = false;
    var initWhenValidatorsLoadedCounter = 0;
  }
  
  // public functions
  
  DataChangeWatcher.startWatching = startWatching;
  DataChangeWatcher.pauseWatching = pauseWatching;
  DataChangeWatcher.resumeWatching = resumeWatching;
  DataChangeWatcher.changeValidator = validate;
  DataChangeWatcher.changeValidatorSkipLineEndings = validateIgnoreLineEndings;
  DataChangeWatcher.changeValidatorCustom = validateCustom;
  DataChangeWatcher.checkIfDataChanged = checkIfDataChanged;
  DataChangeWatcher.confirmIfDataChanged = confirmIfDataChangedAndStopWatching;
  DataChangeWatcher.isWatching = isWatching;
  DataChangeWatcher.setChanged = setChanged;
  DataChangeWatcher.setNotChanged = setNotChanged;
  
  // private functions
  
  function isWatching()
  {
    if (typeof(watch) != 'undefined')
      return watch;
    else
      return null;
  }
  
  function startWatching(validationGroupName, message, forceInit)
  {
    if (forceInit)
    {
      isInited = false;
      watch = false;
    }
    
    if (isInited)
    {
      watch = true;
    }
    else
    {
      if (validationGroupName)
        validationGroup = validationGroupName;
      
      if (message)
        warningMessage  = message;
      
      // we have to start it with timeout - this is for Atlas
      setTimeout(initWhenValidatorsLoaded, 100);
    }
  }
  
  function pauseWatching(source)
  {
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('pause - ' + source);
    watch = false;
  }
  
  function resumeWatching(source)
  {
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('resume - ' + source);
    watch = true;
  }

  function initWhenValidatorsLoaded()
  {
    if (isInited) return;  
     
    initWhenValidatorsLoadedCounter++;
    if (typeof(debugDCW)  != 'undefined' && debugDCW && !BonaPage.isWidgetMode) 
    {
      alert("DCW: init started" +
            "\ntypeof(Page_ValidationActive) = " + typeof(Page_ValidationActive) + 
            "\ntypeof(BonaPage.topWindow.BonaEditor) == " + typeof(BonaPage.topWindow.BonaEditor));
            
      if (typeof(Page_ValidationActive) == 'boolean') 
        alert("DCW: Page_ValidationActive = " + Page_ValidationActive);
        
      if (typeof(BonaPage.topWindow.BonaEditor) != 'undefined')
        alert("DCW: = BonaPage.topWindow.BonaEditor.checkIfAllEditorsLoaded = " + BonaPage.topWindow.BonaEditor.checkIfAllEditorsReady());
   }
    
    // check of Page_ValidationActive is true
    // we can save initial values only if 
    if (typeof(Page_ValidationActive) == 'boolean' && Page_ValidationActive &&
        (BonaPage.isWidgetMode ||
         typeof(BonaPage.topWindow.BonaEditor) == 'undefined' ||
         initWhenValidatorsLoadedCounter > 10 ||
         (typeof(BonaPage.topWindow.BonaEditor) != 'undefined' && BonaPage.topWindow.BonaEditor.checkIfAllEditorsReady())))
    {
      initWhenValidatorsLoadedCounter = 0;
      watch = true;
      var origValidatorUpdateIsValid = ValidatorUpdateIsValid;
      var origValidatorUpdateDisplay = ValidatorUpdateDisplay;
      
      ValidatorUpdateIsValid = function() {};
      ValidatorUpdateDisplay = function() {};
      
      //call validate so validation is performed. 
      //isInited = false and thus DataChangeWatcher.changeValidator will save current values to the senders
      Page_ClientValidate(validationGroup);
      
      ValidatorUpdateIsValid = origValidatorUpdateIsValid;
      ValidatorUpdateDisplay = origValidatorUpdateDisplay;
      
      addOnBeforeUnloadHandler();
      isInited = true;
      initWhenValidatorsLoadedCounter = 0;
      
      if (typeof(debugDCW)  != 'undefined' && debugDCW) alert("DCW: init complete");
    }
    else if (typeof(BonaPage.topWindow.BonaEditor) != 'undefined' && !BonaPage.topWindow.BonaEditor.checkIfAllEditorsReady())
    {
      setTimeout(initWhenValidatorsLoaded, 100);
    }
  }
  
  function validate(sender, args)
  {
    validateCustom(sender.controltovalidate, args.Value, args);
  }
  
  function validateIgnoreLineEndings(sender, args)
  {
    validateCustom(sender.controltovalidate, args.Value, args, true);
  }
  
  function validateCustom(uniqueKey, value, args, ignoreLineEndings)
  {
    var isValid = true;
      
    if (typeof(watch) != 'undefined' && watch)
    {
      if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('DCW: validateCustom\n\nid = ' + uniqueKey);
      if (alreadyChanged) {
        isValid = false;
      } else {
          if (!isInited)
          {
            if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('DCW: validateCustom\n\ninit value = \n"' + value + '"');
            savedValues[uniqueKey] = value;
          }
          else if (savedValues[uniqueKey] != 'undefined')
          {
            if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('DCW: validateCustom\n\nvalueNew = \n"' + value + '"\n\nvalueOld = \n"' + savedValues[uniqueKey] + '"');
            isValid = checkValuesAreEqual(savedValues[uniqueKey] + '', value, ignoreLineEndings);
            if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('DCW: validateCustom\n\nisValid = ' + isValid);
          } 
      }
    }
    
    args.IsValid = isValid;
  }
  
  function checkValuesAreEqual(value1, value2, ignoreLineEndings)
  {
    var valuesEqual;
  
    if (ignoreLineEndings)
    {
        valuesEqual = (value1.replace(/[\n\r\t]+/g, '').replace(/^\s*(.*)\s*$/, '$1') == value2.replace(/[\n\r\t]+/g, '').replace(/^\s*(.*)\s*$/, '$1'));
    }
    else
    {
        valuesEqual = (value1 == value2);
    }
    
    return valuesEqual;
  }

  function checkIfDataChanged()
  {
    var changed = (alreadyChanged) ? true : false;
    
    if (typeof(Page_ClientValidate) != 'undefined')
    {
      changed = !Page_ClientValidate(validationGroup) || changed;    
    }
    
    if (typeof(BonaValidateIfChanged) != 'undefined')
    {
      changed = BonaValidateIfChanged() || changed;
    }
    
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('DCW: checkIfDataChanged = ' + changed);
    
    return changed;
  }

  function confirmIfDataChangedAndStopWatching()
  {
    var confirmed = true;
    
    if (checkIfDataChanged())
    {
      confirmed = confirm(warningMessage);
    }
      
    if (confirmed)
    {
       pauseWatching();
    }

    return confirmed;
  }
  
  function addOnBeforeUnloadHandler()
  {
    var isAdminPanelPresent = false;
    
    try
    {
      if(BonaPage.topWindow.adminpanel)
      {
        isAdminPanelPresent = true;
      }
    }
    catch(e){};

    if (isAdminPanelPresent)
    {
      if (document.all)
      {
        try
        {        
            BonaPage.topWindow.adminpanel.document.body.onbeforeunload = validateBeforeUnloadAdminFrame;
            BonaPage.topWindow.adminpanel.document.body.onunload = pauseWatching;        
            BonaPage.topWindow.contentarea.document.body.onbeforeunload = validateBeforeUnloadContentFrame;
            BonaPage.topWindow.contentarea.document.body.onunload = pauseWatching;        
            BonaPage.topWindow.document.body.onbeforeunload = validateBeforeUnloadFrameSet;
            BonaPage.topWindow.document.body.onunload = pauseWatching;
        }
        catch(e)
        {
            setTimeout(function() { addOnBeforeUnloadHandler(); }, 100);
        }
      }
      else
      {
        BonaPage.topWindow.adminpanel.onbeforeunload = validateBeforeUnloadAdminFrame;
        BonaPage.topWindow.adminpanel.onunload = pauseWatching;
        BonaPage.topWindow.contentarea.onbeforeunload = validateBeforeUnloadContentFrame;
        BonaPage.topWindow.contentarea.onunload = pauseWatching;
        BonaPage.topWindow.onbeforeunload = validateBeforeUnloadFrameSet;
        BonaPage.topWindow.onunload = pauseWatching;
      }
    }
    else
    {
      if (document.all)
      {
        window.document.body.onbeforeunload = validateBeforeUnloadNoFrames;
        window.document.body.onunload = pauseWatching;
      }
      else
      {
        window.onbeforeunload = validateBeforeUnloadNoFrames;
        window.onunload = pauseWatching;
      }
    }
  }
  
  function removeOnBeforeUnloadHandler()
  {
    //globalUtils.removeHandler(window, 'beforeunload', validateBeforeUnload);
  }
  
  function getWarningMessageIfDataChanged()
  {
    var dataChanged = checkIfDataChanged();
    if (dataChanged)
      return warningMessage;
  }
  
  function validateBeforeUnloadNoFrames()
  {
    if (typeof(watch) == 'undefined' || !watch) return;

    var message = getWarningMessageIfDataChanged();

    pauseWatching();
    
    if (document.all)
    {
        window.setTimeout(resumeWatching, 100);
    }
    else
    {
        window.setTimeout(resumeWatching, 100);
    }

    return message;
  }
  
  function validateBeforeUnloadAdminFrame()
  {
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('validateBeforeUnloadAdminFrame');

    if (typeof(watch) == 'undefined' || !watch) return;

    var message = getWarningMessageIfDataChanged();

    pauseWatching();
    
    if (document.all)
    {
        BonaPage.topWindow.adminpanel.setTimeout(resumeWatching, 100);
    }
    else
    {
        BonaPage.topWindow.adminpanel.setTimeout(resumeWatching, 100, 'admin');
    }

    return message;
  }
  
  function validateBeforeUnloadContentFrame()
  {
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('validateBeforeUnloadContentFrame');

    if (typeof(watch) == 'undefined' || !watch) return;

    var message = getWarningMessageIfDataChanged();

    pauseWatching();
    
    if (document.all)
    {
        setTimeout(resumeWatching, 100);
    }
    else
    {
       BonaPage.topWindow.contentarea.setTimeout(resumeWatching, 100, 'content');
    }

    return message;
  }
  
  function validateBeforeUnloadFrameSet()
  {
    if (typeof(debugDCW)  != 'undefined' && debugDCW) alert('validateBeforeUnloadFrameSet');

    if (typeof(watch) == 'undefined' || !watch) return;

    var message = getWarningMessageIfDataChanged();

    pauseWatching();
    
    if (BonaPage)
    {
      if (document.all)
      {
        BonaPage.topWindow.setTimeout(resumeWatching, 100);
      }
      else
      {
        BonaPage.topWindow.contentarea.setTimeout(resumeWatching, 100, 'content');
        BonaPage.topWindow.adminpanel.setTimeout(resumeWatching, 100, 'admin');
      }
    }
    else
    {
      try
      {
        if (document.all)
        {
          top.setTimeout(resumeWatching, 100);
        }
        else
        {
          top.contentarea.setTimeout(resumeWatching, 100, 'content');
          top.adminpanel.setTimeout(resumeWatching, 100, 'admin');
        }
      }
      catch (err) {}
    }

    return message;
  }

  function setChanged() {
    alreadyChanged = true;
  }
  function setNotChanged() {
    alreadyChanged = false;
  }
}) ();

if(typeof(Sys) !== "undefined")
  Sys.Application.notifyScriptLoaded();
