/* F4 probe: trace TrustArc's close message end to end.
 *
 * Round 1 (F4 with the dialog open) settled the second half: all four ids
 * resolve, and calling truste.eu.prefclose() directly REMOVES the overlay --
 * `TACLOSE overlay still present: no`, with REMOVED/CSSREMOVED in the log to
 * match. So the teardown works; what does not work is getting to it from the
 * postMessage the Cancel button sends, which NSDBG/PMSG show being delivered.
 *
 * Everything between delivery and prefclose is inside notice.js and silent:
 *
 *   msgListener: a.data && originSet.has(a.origin) && (parse, shift, dispatch)
 *   dispatchEvent: for (...) try { _listeners[b](a) } catch (d) {}   <- empty
 *
 * so this run wraps each link and reports what it sees. It changes nothing
 * and closes nothing.
 *
 * Open the dialog ("more options"), press F4 ONCE, then click Cancel.
 * Read the TACLOSE lines in logs/NSDBG.TXT.
 */
(function () {
  function out(s) {
    console.log('TACLOSE ' + s);
  }

  function show(v) {
    try {
      return JSON.stringify(v);
    } catch (e) {
      return String(v);
    }
  }

  if (typeof truste === 'undefined' || !truste.eu || !truste.eu.msg) {
    out('no truste.eu.msg on this page');
    return;
  }

  var msg = truste.eu.msg;

  /* The origin gate, read properly this time. (Round 1 printed it with
   * Array.prototype.slice, which answers [] for any Set -- that line said
   * nothing.) */
  var set = msg.originSet;
  if (set && typeof set.forEach === 'function') {
    var items = [];

    set.forEach(function (v) { items.push(v); });
    out('originSet size=' + set.size + ' items=' + show(items) +
        ' has(window.origin)=' + set.has(window.origin));
  } else {
    out('originSet is not a Set: ' + show(set));
  }
  out('window.origin=' + show(window.origin) +
      ' listeners=' + (msg._listeners ? msg._listeners.length : '(none)'));

  /* Link 1: does the window listener run at all, and with what origin?
   * Registered directly on window so it sees the same event notice.js does,
   * whatever its own gate then decides. */
  window.addEventListener('message', function (e) {
    out('raw message: origin=' + show(e.origin) +
        ' typeof data=' + (typeof e.data) +
        ' data=' + String(e.data).slice(0, 160));
  }, false);

  /* Link 2: notice.js's own listener, and whether its gate opens. */
  var origListener = msg.msgListener;
  msg.msgListener = function (a) {
    var pass = false;

    try {
      pass = !!(a && a.data) && msg.originSet.has(a.origin);
    } catch (e) {
      out('msgListener gate threw ' + e);
    }
    out('msgListener origin=' + show(a && a.origin) + ' gate=' +
        (pass ? 'OPEN' : 'CLOSED'));
    return origListener.apply(this, arguments);
  };

  /* Link 3: the dispatcher -- what the message parsed into, and any
   * exception their empty catch would have swallowed. */
  var origDispatch = msg.dispatchEvent;
  msg.dispatchEvent = function (a) {
    var list = msg._listeners || [];

    out('dispatch source=' + show(a && a.source) +
        ' message=' + show(a && a.message) +
        ' data=' + show(a && a.data) +
        ' listeners=' + list.length);

    for (var i = list.length; 0 < i--;) {
      try {
        list[i](a);
      } catch (e) {
        out('listener[' + i + '] threw ' + e + ' @ ' + (e && e.stack));
      }
    }
    return undefined;
  };

  /* Link 4: did anything reach the teardown? */
  var origClose = truste.eu.prefclose;
  truste.eu.prefclose = function () {
    var r;

    out('prefclose called');
    try {
      r = origClose.apply(this, arguments);
    } catch (e) {
      out('prefclose threw ' + e + ' @ ' + (e && e.stack));
      throw e;
    }
    out('prefclose returned ' + show(r) + '; overlay present: ' +
        (document.querySelector('.truste_overlay') ? 'yes' : 'no'));
    return r;
  };

  out('armed -- now click Cancel');
})();
