// Standard JavaScript Utility Methods
// $Id: ctaUtilities.js,v 1.18 2011-07-11 16:18:58 john Exp $

function CTA_Popup(URL, target, args) {
  // Create/lookup the window by target.
  var newWin = window.open(URL, target, args);
  // Ensure the window is focused.
  newWin.focus();
}

function CTA_updateClock (stime, diffTime, prefix) {
  var currentTime = new Date ();
  var clientTime = new Date ();
  if (stime == 0) {
    currentTime.setTime(currentTime.getTime() + diffTime);
  } else {
    currentTime = new Date(stime);
    diffTime = (currentTime.getTime() - clientTime.getTime())/1000;
    diffTime = Math.floor(diffTime) * 1000;
  }
  // Update the time display
  document.getElementById(prefix + "serverclock").firstChild.nodeValue = currentTime.toUTCString().replace(/,/, "").replace(/:[0-9][0-9] /, " ");
  document.getElementById(prefix + "clientclock").firstChild.nodeValue = clientTime.toLocaleString().replace(/:[0-9][0-9] /, " ").replace(/:[0-9][0-9]$/, "");
  return diffTime;
}

function CTA_togglevisibility(element) {
  e = document.getElementById(element);
  if (e.style.visibility=='visible') {
    e.style.visibility='hidden';
  } else {
    e.style.visibility='visible';
  }
}

/** Simple method for toggling display style between 'none' and 'block'.
 * Used by 'alert' message which can be enabled via the WebSettings interface.
 */
function CTA_toggleDisplay(elementId) {
  var element = document.getElementById(elementId);
  if (element.style.display != 'none') {
    element.style.display = 'none';
  } else {
    // That the client wants block is a hell of an assumption, but this is a simplistic method anyway.
    // You can't use 'inherit' because it isn't supported on IE6.
    element.style.display = 'block';
  }
}

/** This method toggles two fields visibility based on whether a checkbox is
 * checked. If checked, field1 row is visible and field input enabled and field2 row is hidden and field input disabled.
 * If not checked, field1 row is hidden and field input disabled and field2 row is visible and field input enabled.
 * If field1 = 'field.name', then it needs a row id 'field.name.row' and an input field 'field.name'.
 */
function CTA_toggleFieldVisibility(checkbox, field1, field2) {
  var checkbox = document.getElementById(checkbox);
  var field1EncapsulatingTag = document.getElementById(field1 + ".row");
  var field2EncapsulatingTag = document.getElementById(field2 + ".row");
  var field1Input = document.getElementById(field1);
  var field2Input = document.getElementById(field2);
  if (checkbox.checked) {
    field1EncapsulatingTag.style.display = "";
    field1Input.disabled = false;
    field2EncapsulatingTag.style.display= "none";
    field2Input.disabled = true;
  } else {
    field1EncapsulatingTag.style.display= "none";
    field1Input.disabled = true;
    field2EncapsulatingTag.style.display= "";
    field2Input.disabled = false;
  }
 }

/** Initialises the ContentSetter on a dijit.Dialog.
 * This allows us to override the set method so we can hook in some script execution
 * before the node is parsed for dojo tags. This is vital if the script nodes contain
 * dojo.require statements which load objects specified in the dojo parse tags.
 */
function CTA_initDojoDialogContentSetter(dijitDialog) {
  dojo.hitch(dijitDialog, function() {
    // NOTE: This is a direct copy of the setter initialisation code from ContentPane in
    // dojo-1.3.2, which is extended by dijit.Dialog.
    var setter = this._contentSetter; 
    if(! (setter && setter instanceof dojo.html._ContentSetter)) {
      setter = this._contentSetter = new dojo.html._ContentSetter({
        node: this.containerNode,
        _onError: dojo.hitch(this, this._onError),
        onContentError: dojo.hitch(this, function(e){
          // fires if a domfault occurs when we are appending this.errorMessage
          // like for instance if domNode is a UL and we try append a DIV
          var errMess = this.onContentError(e);
          try{
            this.containerNode.innerHTML = errMess;
          }catch(e){
            console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
          }
        })
      });
    }
  })();
}

/** Helper used initially by DojoDialogFormActionHandler.
 * This does the job of opening a dialog, but also ensuring any script contents
 * are eval'd and the cancel buttons just close the dialog rather than doing a server roundtrip.
 */
function CTA_showDojoDialog(dojoDialogId, evalScriptNodes) {
  var dojoDialog = dijit.byId(dojoDialogId);
  if (!dojoDialog) {
    console.error("Could not locate dialog: " + dojoDialogId);
  } else {
    // Don't allow user to pull around.
    dojoDialog.draggable = false;

    // We must evaluate the script blocks before the setter parses for dojo tags,
    // in case the script block calls dojo.require on required objects for the parse.
    CTA_initDojoDialogContentSetter(dojoDialog);
    var dialogContentSetter = dojoDialog._contentSetter;
    if (evalScriptNodes) {
      var origParse = dialogContentSetter._parse;
      dialogContentSetter._parse = function() {
        CTA_evalScriptNodes(this.node);
        dojo.hitch(dialogContentSetter, origParse)();
      }
    }
    
    // Override the behaviour of setting content on dialog so we can get consistent sizing.
    var origSetContent = dialogContentSetter.setContent;
    dialogContentSetter.setContent = function() {
      // Dojo campus documents recommend sizing dialog content by creating a wrapper node for the contents.
      // Hence create a div below the container node which we'll use to size the dialog contents, this means
      // we don't rely on the contents providing us a single top level element.
      var origNodeTarget = dialogContentSetter.node;
      var sizedNode = dojo.doc.createElement("div");
      dojo.place(sizedNode, origNodeTarget, "first");
      dojo.style(sizedNode, "overflow", "auto");
      dojo.style(sizedNode, "position", "relative");
      
      // Can't rely on browse percentage sizes, so we'll have to track any window resizing in JS.
      var sizeDialogContents = function() {
        // Don't set just width and height because large dialogs for small messages don't look good.
        // Instead set only max-height. We must set width else dialog doesn't layout correctly in most browsers.
        // Set the height absolutely for IE6, it doesn't support max-height at all.
        var viewport = dijit.getViewport();
        dojo.style(sizedNode, "width", (viewport.w * 0.7) + "px");
        var heightAttr = (dojo.isIE && dojo.isIE == 6) ? "height" : "maxHeight";
        // Note, arbitrary extra px leaves room for dialog title.
        var newHeightPx = (viewport.h * 0.7) - 40;
        if (newHeightPx > 0) {
          dojo.style(sizedNode, heightAttr, newHeightPx + "px");
        }
      }
      sizeDialogContents();
      dialogContentSetter.node = sizedNode;
      
      // Ensure the dialog contents are resized BEFORE the dojo dialog lays itself out (e.g. as a result of browser resize).
      var origLayout = dojoDialog.layout;
      dojoDialog.layout = function() {
        sizeDialogContents();
        dojo.hitch(dojoDialog, origLayout)();
      };
      
      // Now set dialog contents on the sized div, rather than the container node as is the default.
      dojo.hitch(dialogContentSetter, origSetContent)();  
      
      // Dialog superclass will expect the container node to still be on the setter, so set it back.
      dialogContentSetter.node = origNodeTarget;
    }

    // Hookup any 'cancel' button to the dialog close function.
    dojo.connect(dojoDialog, 'onLoad', this, function() {
      var dojoDialogNode = dojo.byId(dojoDialogId);
      var cancelButtons = dojo.query("div.btn input[name*='cancel']", dojoDialogNode);
      cancelButtons.forEach(function(cancelButton) {
        dojo.connect(cancelButton, 'onclick', this, function(event) {
          // Stop the click from going any further.
          event.stopPropagation();
          event.preventDefault();
          dojo.stopEvent(event);

          // Close the dialog.
          dojoDialog.hide();
        });
      });
    });

    dojoDialog.show();
  }
}

/** Find script blocks in the supplied container eval them.
 * This is useful when asynchronously requesting some HTML and wishing to integrate it in a page.
 * Please note this function REQUIRES DOJO.
 * @param containerNode DOM node containing script tags to execute.
 */
function CTA_evalScriptNodes(containerNode) {
  if (containerNode) {
    var appendNode = dojo.doc.body;
    dojo.query("script", containerNode).forEach(function(scriptNode) {
      // Execute script element, technique from dojox.layout.ContentPane.evalInGlobal function.
      // Do not pull in the script if it is a dojo.js import, we should never call dojo.js twice.
      // Do not pull in the script if it is a dojo type e.g. where associated with a dijit. That will
      // get executed when the dijit is parsed by the dojo parser.
      if (!(scriptNode.src && scriptNode.src.match(/dojo.js/)) &&
        !(scriptNode.type && scriptNode.type.match(/dojo/))) {
        var newScriptNode = appendNode.ownerDocument.createElement('script');
        newScriptNode.type = "text/javascript";
        appendNode.appendChild(newScriptNode);
        if (scriptNode.src) {
          newScriptNode.src = scriptNode.src;
        } else {
          newScriptNode.text = scriptNode.innerHTML;
        }
      }
    });
  }
}

/** Used by ComponentExtenderWeb.PerformTask to ensure onclick methods in a wrapped UC are executed
 * if the transition button will call that UC action.
 */
function CTA_performWorkflowTransitionOnClick(ucButtonOnClickId) {
  var ucButtonQuery = dojo.query("input[name='" + ucButtonOnClickId + "']");
  if (ucButtonQuery[0]) {
    // Detect if button has an onclick event.
    var ucButton = ucButtonQuery[0];
    var ucButtonOnClickFunction = ucButton.onclick;
    if (ucButtonOnClickFunction) {
      // Execute the function within the current scope.
      var hitchedFunction = dojo.hitch(this, ucButtonOnClickFunction);
      return hitchedFunction();
    }
  }
  // If we could not locate the onclick then default to allowing the transition to continue.
  console.debug("Could not locate onclick for button: " + ucButtonOnClickId);
  return true;
}

