(function() {



  // YUI Libraries
  var Event = YAHOO.util.Event;


  var XSSTransport = function() {



    /**
     * @description Flag to check if debug mode enabled/disabled
     * @property debug
     * @private
     * @static
     * @type boolean
     */
    var debug = false;



    /**
     * @description Number of initiated XSS requests
     * @property counter
     * @private
     * @static
     * @type integer
     */
    var counter = 0;



    /**
     * @description Prefix used (w/ counter) to construct name of iframe element
     * @property prefix
     * @private
     * @static
     * @type string
     */
    var prefix = 'XSSTransport-';



    /**
     * @description Creates an iframe element to handle the XSS transaction
     * and assigns the callback methods to its onload event
     * @method createSandbox
     * @private
     * @static
     * @param {object} callback Object containing success and failure methods
     * @param {object} scope Object applied callback methods
     * @return DOM element 
     */
    var createSandbox = function(callback, scope) {


      // Generate a unique ID for the sandbox's <IFRAME> element
      var id = prefix.concat(++counter);


      var iframe;
      
      // MSIE
      try {
        iframe = document.createElement('<iframe name="' + id + '"></iframe>');

      // Standards-compliant browsers
      } catch (e) {
        iframe = document.createElement('iframe');
        iframe.name = id;
      }

      if (!debug) {
        iframe.style.display = 'none';
      }

      document.body.appendChild(iframe);


      // Delete <DIV> node

      div = undefined;


      // YAHOO's Event utility has been the most successful method of
      // capturing the <IFRAME> onload event
      // TODO: Figure out why!

      // TODO: Error proof access to the document (document.domain).

      var listener = function() {

        // Extract the content of the returned document

        var doc = null;

        // Firefox, Opera
        if (iframe.contentDocument) {
          doc = iframe.contentDocument;
        // MSIE
        } else if (iframe.contentWindow) {
          doc = iframe.contentWindow.document;
        // etc.
        } else if (iframe.document) {
          doc = iframe.document;
        }

        try {

          var html = doc.body.innerHTML;

        } catch(e) {
          
          var error = "Unable to complete XSSTransport request.\n\n" + e + "\n\nPlease check that document.domain is set properly."; 
          
          callback.failure.call(scope || window, error);
          
          throw e;
        }                                  
        
        // Capture the frame src
        var src = iframe.src;

        // Fix possible greedy frames
        setTimeout(function() {
          fixJumpingFrames(src);
        }, 100);

        // Wrap the DOM cleanup in setTimeout to avoid
        // an endless spinning cursor in Firefox
        // TODO: Google this issue
        setTimeout(function() {

          // Remove event listener
          Event.removeListener(iframe, 'load', listener);
                
          // Remove iframe DOM element
          if (!debug) {
            iframe.parentNode.removeChild(iframe);
          }
        }, 0);

        // Execute the callback function
        callback.success.call(scope || window, html);
                
      };
      Event.on(iframe, 'load', listener);

      return iframe;
    };


    var fixJumpingFrames = function(src) {

      var wf = window.frames;
      
      for (var i = 0, len = wf.length; i < len; ++i) {

        var f = wf[i];

        // Ignore XSSTransport iframes
        try {
          if (f.name.indexOf(prefix) === 0) {
            // console.log('Skipping window.frame['+i+']: ' + f.name);
            continue;
          }
        } catch(e) {}

        try {
          var d = f.document.domain;
          var l = f.location.href;
          var s = f.frameElement.src;
        } catch(e) {
          // console.log('Unable to access window.frame['+i+'].document');
          continue;
        }

        // If location.href matches the XSSTransport src,
        // set the location.href = frameElement.src
        // if (unescape(l) == unescape(src)) {
          if (unescape(l) != unescape(s)) {
          // console.log("FIXING window.frame["+i+"]\n\n" + l + "\n\n"  + s);
          // console.log(f);
          f.location.href = s;
        }

      }
    };


    return {



      /**
       * @description Enable debugging of XSS transactions by displaying hidden
       * iframe and form elements
       * @method enableDebugging
       * @public
       * @static
       * @return void
       */
      enableDebugging: function() {
        debug = true;
      },



      /**
       * @description Member to override the default POST header.
       * @method setDefaultPostHeader
       * @public
       * @static
       * @param {boolean} b Set and use default header - true or false .
       * @return void
       */
      disableDebugging: function() {
        debug = false;
      },



      /**
       * Method description
       *
       * @method methodName
       * @static
       * @param  {type} paramName  Parameter description
       * @return {type} Return value description
       */
      getRequest: function(uri, callback, scope) {
        
        var sandbox = createSandbox(callback, scope);

        sandbox.src = uri;
      },



      /**
       * Method description
       *
       * @method methodName
       * @static
       * @param  {type} paramName  Parameter description
       * @return {type} Return value description
       */
      postRequest: function(uri, data, callback, scope) {

        var sandbox = createSandbox(callback, scope);

        var form = document.createElement('form');

        form.action = uri;
        form.method = 'post';
        form.target = sandbox.name;

        for (var key in data) {

          if (debug) {
            var label = document.createElement('label');
            label.appendChild(document.createTextNode(key));
            document.body.appendChild(label);
          }

          var input = document.createElement('input');

          input.type  = (debug) ? 'text' : 'hidden';
          input.name  = key;
          input.value = data[key];

          form.appendChild(input);
        }

        document.body.appendChild(form);

        form.submit();
        
        if (!debug) {
          document.body.removeChild(form);
        }
      }

    };
  }();


  
  // Add XSSTransport to TIME.util namespace
  window.TIME = window.TIME || YAHOO.namespace('TIME');  
  YAHOO.namespace('TIME.util');
  TIME.util.XSSTransport = XSSTransport;


})();