
function target_test(...args)
{
    if (args.length !== 2 && args.length !== 3) {
        console.error(`target_test expected 2 or 3 arguments but got ${args.length}.`);
        return;
    }

    const impliedOptions = args.length == 2;

    let options = impliedOptions ? { } : args[0];
    let continutation = args[impliedOptions ? 0 : 1];
    let description = args[impliedOptions ? 1 : 2];

    options.x = options.x || 0;
    options.y = options.y || 0;
    options.width = options.width || "100%";
    options.height = options.height || "100%";

    async_test(test => {
        const target = document.body.appendChild(document.createElement("div"));
        target.setAttribute("style", `
            position: absolute;
            left: ${options.x};
            top: ${options.y};
            width: ${options.width};
            height: ${options.height};
        `);
        test.add_cleanup(() => target.remove());

        continutation(target, test);
    }, description);
}

class EventTracker
{
    constructor(target, eventNames)
    {
        this.target = target;
        this.events = [];
        this.pointerIdToTouchIdMap = {};

        for (let eventName of eventNames)
            target.addEventListener(eventName, this);
    }

    clear()
    {
        this.events = [];
    }

    handleEvent(event)
    {
        if (event instanceof PointerEvent)
            this._handlePointerEvent(event);
        else if (event instanceof MouseEvent)
            this._handleMouseEvent(event);
    }

    _handlePointerEvent(event)
    {
        if (!this.pointerIdToTouchIdMap[event.pointerId])
            this.pointerIdToTouchIdMap[event.pointerId] = Object.keys(this.pointerIdToTouchIdMap).length + 1;

        this.events.push({
            id: this.pointerIdToTouchIdMap[event.pointerId],
            type: event.type,
            x: event.clientX,
            y: event.clientY,
            pressure: event.pressure,
            isPrimary: event.isPrimary,
            isTrusted: event.isTrusted
        });
    }

    _handleMouseEvent(event)
    {
        this.events.push({
            type: event.type,
            x: event.clientX,
            y: event.clientY,
        });
    }

    assertMatchesEvents(expectedEvents)
    {
        assert_true(!!this.events.length, "Event tracker saw some events.");
        assert_equals(expectedEvents.length, this.events.length, "Expected events and actual events have the same length.");
        for (let i = 0; i < expectedEvents.length; ++i) {
            const expectedEvent = expectedEvents[i];
            const actualEvent = this.events[i];
            for (let property of Object.getOwnPropertyNames(expectedEvent))
                assert_equals(expectedEvent[property], actualEvent[property], `Property ${property} matches for event at index ${i}.`);
        }
    }
}

const ui = new (class UIController {

    constructor()
    {
        this.fingers = {};
    }

    finger()
    {
        const id = Object.keys(this.fingers).length + 1;
        return this.fingers[id] = new Finger(id);
    }

    swipe(from, to)
    {
        const durationInSeconds = 0.1;
        return new Promise(resolve => this._run(`uiController.dragFromPointToPoint(${from.x}, ${from.y}, ${to.x}, ${to.y}, ${durationInSeconds})`).then(() =>
            setTimeout(resolve, durationInSeconds * 1000)
        ));
    }

    tap(options)
    {
        // Add a delay to ensure sequence of tap() calls don't yield double taps.
        const delay = 1000;
        return this._run(`uiController.singleTapAtPoint(${options.x}, ${options.y})`).then(() => {
            return new Promise(resolve => setTimeout(resolve, delay));
        });
    }

    pinchOut(options)
    {
        options.x = options.x || 0;
        options.y = options.y || 0;

        const startPoint = { x: options.x + options.width, y: options.y + options.height };
        const endPoint = { x: options.x + options.width * options.scale, y: options.y + options.height * options.scale };

        function step(factor)
        {
            return {
                x: endPoint.x + (startPoint.x - endPoint.x) * (1 - factor),
                y: endPoint.y + (startPoint.y - endPoint.y) * (1 - factor)
            };
        }

        const one = this.finger();
        const two = this.finger();
        return this.sequence([
            one.begin({ x: options.x, y: options.y }),
            two.begin(step(0)),
            two.move(step(0.2)),
            two.move(step(0.4)),
            two.move(step(0.6)),
            two.move(step(0.8)),
            two.move(step(1)),
            one.end(),
            two.end()
        ]);
    }

    sequence(touches)
    {
        const activeFingers = {};

        return this._runEvents(touches.map((touches, index) => {
            if (!Array.isArray(touches))
                touches = [touches];

            const processedIDs = {};

            // Update the list of active touches.
            touches.forEach(touch => {
                processedIDs[touch.id] = true;
                if (touch.phase === "ended")
                    delete activeFingers[touch.id];
                else
                    activeFingers[touch.id] = { x: touch.x, y: touch.y };
            });

            // Now go through the active touches and check that they're all listed in the new touches.
            for (let id in activeFingers) {
                if (!processedIDs[id])
                    touches.push(this.fingers[id].stationary(activeFingers[id]));
            }

            return {
                inputType : "hand",
                timeOffset : index * 0.05,
                coordinateSpace : "content",
                touches : touches
            }
        }));
    }

    tapStylus(options)
    {
        options.azimuthAngle = options.azimuthAngle || 0;
        options.altitudeAngle = options.altitudeAngle || 0;
        options.pressure = options.pressure || 0;
        return this._run(`uiController.stylusTapAtPoint(${options.x}, ${options.y}, ${options.azimuthAngle}, ${options.altitudeAngle}, ${options.pressure})`);
    }

    _runEvents(events)
    {
        return this._run(`uiController.sendEventStream('${JSON.stringify({ events })}')`);
    }

    _run(command)
    {
        return new Promise(resolve => testRunner.runUIScript(`(function() {
            (function() { ${command} })();
            uiController.uiScriptComplete();
        })();`, resolve));
    }

})();

class Finger
{

    constructor(id)
    {
        this.id = id;
    }

    begin(options)
    {
        return this._action("began", options.x || 0, options.y || 0);
    }

    move(options)
    {
        return this._action("moved", options.x || 0, options.y || 0);
    }

    end(options)
    {
        return this._action("ended", this._lastX, this._lastY);
    }

    stationary(options)
    {
        return this._action("stationary", options.x || this._lastX, options.y || this._lastY, options.pressure || 0);
    }

    _action(phase, x, y, pressure = 0)
    {
        this._lastX = x;
        this._lastY = y;
        return { inputType: "finger", id: this.id, phase, x, y, pressure };
    }

}
