/* (C) Metaswitch Networks 2009 */

/**
 * This script file must be included by all pages that has the CommPortal
 * embedded. It has functions to allow the CP to open, for instance, the
 * SIP Phone Configuration UI as an overlay instead of opening as a new window.
 * Note that theses pages will not include any CommPortal files, hence it will
 * not be possible to access utils.js or widgets.js, for instance.
 */
function PopupOverlay()
{
}

/**
 * Function that opens an overlay. It hides the scrollbars, applies a
 * background the surrounding and calls the method to create the overlay.
 *
 * @param {String} docRef the reference to the page's document.
 * @param {String} cpPath the reference to the CommPortal's URL.
 * @param {String} url the url to be opened in the overlay or in a new window.
 * @param {String} closeString string used by the popup overlay close button.
 */
PopupOverlay.openUI = function(docRef, cpPath, url, closeString)
{
  // Get reference to the body and to the html. These should point to the
  // elements of the surrounding page in case the CP is embedded. Otherwise
  // it points to the CP elements.
  var bodyRef = docRef.getElementsByTagName("body")[0];
  var htmlRef = docRef.getElementsByTagName("html")[0];

  // If there are no visible scrollbars there is no need to try to hide them.
  if (htmlRef.style.overflow != 'hidden')
  {
    htmlRef.oldScrollLeft = htmlRef.scrollLeft;
    htmlRef.oldScrollTop = htmlRef.scrollTop;

    htmlRef.scrollLeft = 0;
    htmlRef.scrollTop = 0;

    // Store the current value to restore it when closing the overlay.
    htmlRef.oldOverflowValue = htmlRef.style.overflow;

    // Hide the scroll bars
    htmlRef.style.overflow = 'hidden';
  }

  // Show the overlay
  PopupOverlay.showOverlay(docRef, bodyRef, cpPath, url, closeString);

  // Apply a background to cover the surrounding
  PopupOverlay.hideSurrounding(bodyRef);
};

/**
 * Function that applies the background to the surrounding.
 * @param {String} bodyRef the reference to the body.
 */
PopupOverlay.hideSurrounding = function(bodyRef)
{
  var curtain = bodyRef.ownerDocument.createElement('div');
  curtain.id = 'popupOverlayBackground';

  bodyRef.appendChild(curtain);
};

/**
 * Function that adjusts the size of the Phone Configurator UI overlay, so that
 * the overlay is always as visible as possible when the user resizes their
 * browser window.
 */
PopupOverlay.adjustOverlaySize = function()
{
  var overlay = parent.document.getElementById('popupOverlayDiv');
  var iframe = parent.document.getElementById('popupOverlayIframe');

  // Make sure the overlay exists before we start setting its properties
  if (overlay && iframe)
  {
    width = parent.window.innerWidth ?
                                   parent.window.innerWidth :
                                   parent.document.documentElement.clientWidth;

    height = parent.window.innerHeight ?
                                  parent.window.innerHeight :
                                  parent.document.documentElement.clientHeight;

    // Adjust the overlay's left offset
    if ((0.8 * width) < overlay.clientWidth)
    {
      overlay.style.left = String(Math.floor((width -
                                              overlay.clientWidth)/ 2)) + "px";
    }
    else
    {
      overlay.style.left = "10%";
    }

    // Adjust the overlay's top offset
    if ((0.8 * height) < overlay.clientHeight)
    {
      overlay.style.top = String(Math.floor((height -
                                             overlay.clientHeight)/ 2)) + "px";
    }
    else
    {
      overlay.style.top = "10%";
    }

    // The height of the iframe is dynamically calculated to make sure it is
    // always within boundaries, with a 1% margin in the top and at least 30
    // pixels in the bottom.
    iframe.style.height = String(
                           Math.floor(0.98 * overlay.clientHeight - 30)) + "px";
  }
}

/**
 * Function that creates the overlay HTML elements. We always create the HTML
 * elements and then destroy them after closing the overlay. This is done
 * instead of creating it just once and then reusing because when testing both
 * solutions the one that creates the elements again shows a better user
 * experience.
 *
 * @param {String} docRef the reference to the page's document.
 * @param {String} bodyRef the reference to the body.
 * @param {String} cpPath the reference to the CommPortal's URL.
 * @param {String} url the url to be opened in the overlay.
 * @param {String} closeString string used by the popup overlay close button.
 *
 */
PopupOverlay.showOverlay = function(docRef, bodyRef, cpPath, url, closeString)
{
  // Create the popup div
  var popupOverlayDiv = docRef.createElement('div');
  popupOverlayDiv.id = 'popupOverlayDiv';

  // Get the button background image and set the style to the HTML button
  // elements when creating the overlay elements. This is not done in the CSS
  // file because the path to the IMG may be different depending whether the
  // CP is running embedded in another page or not.
  var buttonImg = cpPath + "img/buttons/btn.gif";
  var buttonStyle = "style='background-image:url(" + buttonImg + ");'";

  // Create the HTML elements and add it to the page
  popupOverlayDiv.innerHTML =
             "<iframe src='" + url + "' id='popupOverlayIframe'></iframe>"    +
             "<div class='popupOverlayBottom'>" +
               "<div id='popupOverlayButton'"+ buttonStyle +"class='button'>" +
                 "<a onclick='return PopupOverlay.closeUI();' " + buttonStyle +
                    "href='#'>" + closeString + "</a>" +
               "</div>" +
             "</div>";
  bodyRef.appendChild(popupOverlayDiv);

  // Make sure the popup is properly sized when we open it
  PopupOverlay.adjustOverlaySize();

  // Attach the new resize function to the page.
  if (parent.window.attachEvent)
  {
    // The attachEvent is an IE specific function which does not overwrite the
    // existing events, but appends the new one into the events chain.
    // Therefore we do not need to call the old one.
    parent.window.attachEvent("onresize", PopupOverlay.adjustOverlaySize);
  }
  else
  {
    // Make sure we preserve any existing onResize function
    var oldOnResize = parent.window.onresize;

    parent.window.onresize = function()
    {
      if (oldOnResize)
      {
        oldOnResize.call();
      }

      PopupOverlay.adjustOverlaySize();
    };
  }
};

/**
 * Function that handles the overlay closure. It checks whether there were any
 * changes, and displays a dialog informing that modificactions were made and
 * asks if the user really wants to leave and discard the changes.
 */
PopupOverlay.closeUI = function()
{
  var bodyRef = document.getElementsByTagName("body")[0];
  var popupOverlayRef = document.getElementById("popupOverlayDiv");

  if (PopupOverlay.confirmNavigate(popupOverlayRef))
  {
    var htmlRef = document.getElementsByTagName("html")[0];

    // Reset body dimension properties altered previously when opening the
    // overlay.
    bodyRef.style.height = '';
    bodyRef.style.width = '';

    if (htmlRef.oldOverflowValue != null)
    {
      // Restore the previous scroll bars
      htmlRef.style.overflow = htmlRef.oldOverflowValue;
      htmlRef.scrollLeft = htmlRef.oldScrollLeft;
      htmlRef.scrollTop = htmlRef.oldScrollTop;
    }

    // Remove background
    var curtain = document.getElementById('popupOverlayBackground');
    bodyRef.removeChild(curtain);

    // Remove overlay
    bodyRef.removeChild(popupOverlayRef);
  }

  return false;
};

/**
 * Warn the user if there were any changes in the page asking him to confirm if
 * he really wants to navigate away losing the changes.
 *
 * @param popupOverlayDiv a reference to the HTML div element of the popup
 *                        overlay.
 * @return answer the option chose by the user
 */
PopupOverlay.confirmNavigate = function(popupOverlayDiv)
{
  // Holds the user decision of navigating away when there are unsaved changes
  var answer = true;

  // The beforeUnload function is only available when the page to be opened as
  // overlay is loaded. If the user tries to close the overlay before the page
  // has loaded, we return true so that the dialog can be closed.
  if (popupOverlayDiv.firstChild.contentWindow.beforeUnload)
  {
    // IE complains when createEvent is used, therefore, we create a dummy
    // object to emulate an event since just the returnValue set up by the
    // onbeforeunload handler is needed.
    var dummyEvent = new Object();

    // Add returnValue property
    dummyEvent.returnValue;

    // Trigger the onbeforeunload event handler as we would be 'closing the
    // window'.
    popupOverlayDiv.firstChild.contentWindow.beforeUnload(dummyEvent);

    // Check whether there are pending changes
    if (dummyEvent.returnValue)
    {
      // Ask the user if he/she wants to save any configuration before
      // navigating away.
      answer = confirm(dummyEvent.returnValue);
    }
  }

  return answer;
}
