// This is a helper file used for the automatic-beacon-*.https.html tests.
// To use this, make sure you import these scripts:
// <script src="/resources/testharness.js"></script>
// <script src="/resources/testharnessreport.js"></script>
// <script src="/common/utils.js"></script>
// <script src="/common/dispatcher/dispatcher.js"></script>
// <script src="resources/utils.js"></script>
// <script src="/resources/testdriver.js"></script>
// <script src="/resources/testdriver-actions.js"></script>
// <script src="/resources/testdriver-vendor.js"></script>
// <script src="/common/get-host-info.sub.js"></script>

const NavigationTrigger = {
  Click: 0,
  ClickOnce: 1,
  CrossOriginClick: 2,
  CrossOriginClickNoOptIn: 3
};

// Registers an automatic beacon in a given remote context frame, and registers
// the navigation handler for the frame that will trigger the beacon.
//     remote_context: The context for the fenced frame or URN iframe.
//      beacon_events: An array of FenceEvents to register with the frame.
//     navigation_url: The URL the frame will navigate to.
// navigation_trigger: How the navigation will be performed. Either through a
//                     click, a click with a `once` event, a click in a
//                     cross-origin subframe, or a click in a cross-origin
//                     subframe with no opt-in header.
//             target: the target of the navigation. Either '_blank' or
//                     '_unfencedTop'.
async function setupAutomaticBeacon(
    remote_context, beacon_events, navigation_url = 'resources/dummy.html',
    navigation_trigger = NavigationTrigger.Click, target = '_blank') {
  const full_url = new URL(navigation_url, location.href);
  await remote_context.execute(
      async (
          NavigationTrigger, beacon_events, navigation_trigger, full_url,
          target) => {
        switch (navigation_trigger) {
          case NavigationTrigger.Click:
            addEventListener('click', (event) => {
              beacon_events.forEach((beacon_event) => {
                window.fence.setReportEventDataForAutomaticBeacons(
                    beacon_event);
              });
              window.open(full_url, target);
            });
            break;
          case NavigationTrigger.ClickOnce:
            beacon_events.forEach((beacon_event) => {
              window.fence.setReportEventDataForAutomaticBeacons(beacon_event);
            });
            addEventListener('click', (event) => {
              window.open(full_url, target);
            });
            break;
          case NavigationTrigger.CrossOriginClick:
          case NavigationTrigger.CrossOriginClickNoOptIn:
            beacon_events.forEach((beacon_event) => {
              window.fence.setReportEventDataForAutomaticBeacons(beacon_event);
            });
            // Add a cross-origin iframe that will perform the top-level
            // navigation.
            const iframe = await attachIFrameContext({
              origin: get_host_info().HTTPS_REMOTE_ORIGIN,
              headers: [[
                'Allow-Fenced-Frame-Automatic-Beacons',
                navigation_trigger == NavigationTrigger.CrossOriginClick ?
                    'true' :
                    'false'
              ]]
            });
            await iframe.execute(async (full_url, target) => {
              addEventListener('click', (event) => {
                window.open(full_url, target);
              });
            }, [full_url, target]);
            break;
        }
      },
      [NavigationTrigger, beacon_events, navigation_trigger, full_url, target]);
}

// Checks if an automatic beacon of type `event_type` with contents `event_data`
// was sent out or not.
//        event_type: The automatic beacon type to check.
//        event_data: The automatic beacon data to check.
// expected_referrer: The expected referrer header, if different from origin.
//  expected_success: Whether we expect the automatic beacon to be sent.
//                 t: The WPT's test object. Only required if
//                   expected_success = false.
async function verifyBeaconData(
    event_type, event_data, expected_referrer = null, expected_success = true,
    t) {
  if (expected_success) {
    const data = await nextBeacon(event_type, event_data);
    const [beacon_initiator_origin, beacon_referrer] =
        data.split(",");
    assert_equals(beacon_initiator_origin, get_host_info().HTTPS_ORIGIN,
        "The initiator origin should be set as expected.");
    // The Referer header has a trailing '/' appended to the URL.
    assert_equals(beacon_referrer,
        (expected_referrer ? expected_referrer :
        get_host_info().HTTPS_ORIGIN) + "/",
        "The beacon referrer should be set as expected.");
  } else {
    const timeout = new Promise(r => t.step_timeout(r, 1000));
    const result =
        await Promise.race([nextBeacon(event_type, event_data), timeout]);
    assert_true(typeof result === 'undefined',
        "The beacon should not have sent.");
  }
}
