'use strict'

/** Moves the mouse to the center of |element|. */
const mouseMoveToCenter = element => {
  const clientRect = element.getBoundingClientRect();
  const centerX = (clientRect.left + clientRect.right) / 2;
  const centerY = (clientRect.top + clientRect.bottom) / 2;
  if (window.eventSender)
    eventSender.mouseMoveTo(centerX, centerY);
};

/**
 * Recursively loads content into a series of nested iframes.
 * Returns a Promise that resolves with the HTMLDocument of the innermost frame.
 */
const loadNestedFrames = async domRoot => {
  const frame = domRoot.querySelector('iframe');
  if (!frame)
    return domRoot;

  const htmlSourceId = frame.getAttribute('data-source');
  frame.srcdoc = document.getElementById(htmlSourceId).textContent;
  const frameLoaded = new Promise(resolve => { frame.onload = resolve; });
  await frameLoaded;

  return await loadNestedFrames(frame.contentDocument);
};

/** Retrieves an element with id in an arbitrarily deep nesting of iframes. */
const getElementByIdAcrossIframes = (domRoot, id) => {
  if (!domRoot)
    return null;

  const dragBox = domRoot.getElementById(id);
  if (dragBox)
    return dragBox;

  return getElementByIdAcrossIframes(
      domRoot.querySelector('iframe').contentDocument, id);
};

const loadIframe = async () => {
  await loadNestedFrames(document);
  return document.getElementById('outer-iframe');
};

const loadImage = async () => {
  const image = document.createElement('img');
  image.src = '../resources/greenbox.png';

  const imageLoaded = new Promise(resolve => {
    image.onload = resolve(image);
    document.getElementById('moved-item-source').appendChild(image);
  });
  return await imageLoaded;
};

const loadMovedItem = async loadItem => {
  if (loadItem.includes('iframe'))
    return await loadIframe();
  else if (loadItem.includes('image'))
    return await loadImage();
};

/**
 * Test if moving an element (iframe or image) will cancel dragging by
 *     resetting drag source.
 * testCase: a testCase to test, containing a specified type to load and
 *     whether or not dragend is expected to fire, as well as the action
 *     to attempt.
 */
const dragDomMoveTest = testCase => {
  promise_test(async t => {
    document.querySelector('#test-description').textContent =
        JSON.stringify(testCase);

    const gotEvent = {
      dragStart: false,
      dragOver: false,
      drop: false,
      dragEnd: false,
    };

    let movedItem = await loadMovedItem(testCase.load);
    const dragBox = getElementByIdAcrossIframes(document, 'drag-box');
    const dropBox = document.getElementById('drop-box');
    const doneButton = document.createElement('button');

    dragBox.ondragstart = t.step_func(e => {
      gotEvent.dragStart = true;
      e.dataTransfer.setData('text/plain', 'Needed to work in Firefox');
    });
    dropBox.ondragover = t.step_func(e => {
      gotEvent.dragOver = true;
      e.preventDefault();
    });

    const dndTest = new Promise(resolve => {
      dragBox.ondragend = t.step_func(e => {
        gotEvent.dragEnd = true;
        return resolve();
      });
      dropBox.ondrop = t.step_func(async e => {
        gotEvent.drop = true;
        e.preventDefault();

        const movedItemDestination =
            document.getElementById('moved-item-destination');
        const movedItemSource =
            document.getElementById('moved-item-source');

        // Test whether dragging away or detaching movedItem
        // will disable dragging.
        if (testCase.action == 'removeChild')
          movedItem = movedItem.parentNode.removeChild(movedItem);
        else if (testCase.action == 'appendChild')
          movedItemDestination.appendChild(movedItem);
        else
          return reject("Error: Invalid testCase.action. Please make sure the testCase is spelled correctly");

        // Click to resolve test as backup in case dragend never triggers to
        // end the test.
        setTimeout(() => {
          const clickEvent = new Event('click');
          doneButton.dispatchEvent(clickEvent);
        }, 100);

        // Reset iframe location to teardown and prep for next test.
        if (testCase.load.includes('iframe')) {
          const movedItemLoaded = new Promise(resolve => {
            movedItem.onload = resolve;
            setTimeout(() => { movedItemSource.appendChild(movedItem); }, 100);
          });

          await movedItemLoaded;
        }
      });

      doneButton.onclick = t.step_func(() => {
        return resolve();
      })

      // Do drag and drop.
      if (window.eventSender) {
        mouseMoveToCenter(dragBox);
        eventSender.mouseDown();
        setTimeout(() => {
          mouseMoveToCenter(dropBox);
          eventSender.mouseUp();
        }, 100);
      }
    });
    await dndTest;

    assert_true(gotEvent.dragStart,
        'drag-box should have gotten a dragstart event');
    assert_true(gotEvent.dragOver,
        'drop-box should have gotten a dragover event');
    assert_true(gotEvent.drop,
        'drop-box should have gotten a drop event');
    assert_equals(gotEvent.dragEnd, testCase.expectDragEnd,
        'drag-box should have gotten a dragEnd event');
  }, `tested with input: ${testCase.load}, ${testCase.action}`);
};

const dragDomMoveTests = testCases => {
  for (let testCase of testCases)
    dragDomMoveTest(testCase);

  promise_test(() => {
    return Promise.resolve().then(() => {
      document.querySelector('#test-description').textContent = 'done';
    });
  }, 'all tests complete');
}
