'use strict';

// This script depends on the following script:
//    /file-system-access/resources/test-helpers.js
//    /service-workers/service-worker/resources/test-helpers.sub.js

// Define the URL constants used for each type of message target, including
// iframes and workers.
const kDocumentMessageTarget = 'resources/message-target.html';
const kSharedWorkerMessageTarget = 'resources/message-target-shared-worker.js';
const kServiceWorkerMessageTarget =
  'resources/message-target-service-worker.js';
const kDedicatedWorkerMessageTarget =
  'resources/message-target-dedicated-worker.js';

function create_dedicated_worker(test, url) {
  const dedicated_worker = new Worker(url);
  test.add_cleanup(() => {
    dedicated_worker.terminate();
  });
  return dedicated_worker;
}

async function create_service_worker(test, script_url, scope) {
  const registration = await service_worker_unregister_and_register(
    test, script_url, scope);
  test.add_cleanup(() => {
    return registration.unregister();
  });
  return registration;
}

// Creates an iframe and waits to receive a message from the iframe.
// Valid |options| include src, srcdoc and sandbox, which mirror the
// corresponding iframe element properties.
async function add_iframe(test, options) {
  const iframe = document.createElement('iframe');

  if (options.sandbox !== undefined) {
    iframe.sandbox = options.sandbox;
  }

  if (options.src !== undefined) {
    iframe.src = options.src;
  }

  if (options.srcdoc !== undefined) {
    iframe.srcdoc = options.srcdoc;
  }

  document.body.appendChild(iframe);
  test.add_cleanup(() => {
    iframe.remove();
  });

  await wait_for_loaded_message(self);
  return iframe;
}

// Creates a child window using window.open() and waits to receive a message
// from the child window.
async function open_window(test, url) {
  const child_window = window.open(url);
  test.add_cleanup(() => {
    child_window.close();
  });
  await wait_for_loaded_message(self);
  return child_window;
}

// Wait until |receiver| gets a message event with the data set to 'LOADED'.
// The postMessage() tests use messaging instead of the loaded event because
// cross-origin child windows from window.open() do not dispatch the loaded
// event to the parent window.
async function wait_for_loaded_message(receiver) {
  const message_promise = new Promise((resolve, reject) => {
    receiver.addEventListener('message', message_event => {
      if (message_event.data === 'LOADED') {
        resolve();
      } else {
        reject('The message target must receive a "LOADED" message response.');
      }
    });
  });
  await message_promise;
}

// Sets up a new message channel. Sends one port to |target| and then returns
// the other port.
function create_message_channel(target, target_origin) {
  const message_channel = new MessageChannel();

  const message_data =
    { type: 'receive-message-port', message_port: message_channel.port2 };
  target.postMessage(
    message_data,
    {
      transfer: [message_channel.port2],
      targetOrigin: target_origin
    });
  message_channel.port1.start();
  return message_channel.port1;
}

// Creates a variety of different FileSystemFileHandles for testing.
async function create_file_system_handles(test, root) {
  // Create some files to use with postMessage().
  const empty_file = await createEmptyFile(test, 'empty-file', root);
  const first_file = await createFileWithContents(
    test, 'first-file-with-contents', 'first-text-content', root);
  const second_file = await createFileWithContents(
    test, 'second-file-with-contents', 'second-text-content', root);

  // Create an empty directory to use with postMessage().
  const empty_directory = await createDirectory(test, 'empty-directory', root);

  // Create a directory containing both files and subdirectories to use
  // with postMessage().
  const directory_with_files =
    await createDirectory(test, 'directory-with-files', root);
  await createFileWithContents(test, 'first-file-in-directory',
    'first-directory-text-content', directory_with_files);
  await createFileWithContents(test, 'second-file-in-directory',
    'second-directory-text-content', directory_with_files);
  const subdirectory =
    await createDirectory(test, 'subdirectory', directory_with_files);
  await createFileWithContents(test, 'first-file-in-subdirectory',
    'first-subdirectory-text-content', subdirectory);

  return [
    empty_file,
    first_file,
    second_file,
    // Include the same FileSystemFileHandle twice.
    second_file,
    empty_directory,
    // Include the Same FileSystemDirectoryHandle object twice.
    empty_directory,
    directory_with_files
  ];
}

// Tests sending an array of FileSystemHandles to |target| with postMessage().
// The array includes both FileSystemFileHandles and FileSystemDirectoryHandles.
// After receiving the message, |target| accesses all cloned handles by
// serializing the properties of each handle to a JavaScript object.
//
// |target| then responds with the resulting array of serialized handles. The
// response also includes the array of cloned handles, which creates more
// clones. After receiving the response, this test runner verifies that both
// the serialized handles and the cloned handles contain the expected properties.
async function do_post_message_test(
  test, root_dir, receiver, target, target_origin) {
  // Create and send the handles to |target|.
  const handles =
    await create_file_system_handles(test, root_dir, target, target_origin);
  target.postMessage(
    { type: 'receive-file-system-handles', cloned_handles: handles },
    { targetOrigin: target_origin });

  // Wait for |target| to respond with results.
  const event_watcher = new EventWatcher(test, receiver, 'message');
  const message_event = await event_watcher.wait_for('message');
  const response = message_event.data;

  assert_equals(response.type, 'receive-serialized-file-system-handles',
    'The test runner must receive a "serialized-file-system-handles" ' +
    `message response. Actual response: ${response}`);

  // Verify the results.
  const expected_serialized_handles = await serialize_handles(handles);

  assert_equals_serialized_handles(
    response.serialized_handles, expected_serialized_handles);

  await assert_equals_cloned_handles(response.cloned_handles, handles);
}

// Runs the same test as do_post_message_test(), but uses a MessagePort.
// This test starts by establishing a message channel between the test runner
// and |target|. Afterwards, the test sends FileSystemHandles through the
// message port channel.
async function do_message_port_test(test, root_dir, target, target_origin) {
  const message_port = create_message_channel(target, target_origin);
  await do_post_message_test(
      test, root_dir, /*receiver=*/ message_port, /*target=*/ message_port);
}
