/*
 * Copyright (C) 2015, 2016 Ericsson AB. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name of Ericsson nor the names of its contributors
 *    may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// @conditional=ENABLE(WEB_RTC)
// @internal

// Operation queue as specified in section 4.3.1 (WebRTC 1.0)
function enqueueOperation(peerConnection, operation)
{
    "use strict";

    const operations = peerConnection.@operations;

    function runNext() {
        operations.@shift();
        if (operations.length)
            operations[0]();
    };

    return new @Promise(function (resolve, reject) {
        operations.@push(function() {
            operation().@then(resolve, reject).@then(runNext, runNext);
        });

        if (operations.length == 1)
            operations[0]();
    });
}

function objectAndCallbacksOverload(args, functionName, objectInfo, promiseMode, legacyMode)
{
    "use strict";

    let argsCount = args.length;
    let objectArg = args[0];
    let objectArgOk = false;

    const hasMatchingType = objectArg instanceof objectInfo.constructor;
    if (hasMatchingType)
        objectArgOk = true;
    else if (objectArg == null && objectInfo.defaultsToNull) {
        objectArgOk = true;
        objectArg = null;
    } else if (objectInfo.maybeDictionary) {
        try {
            objectArg = new objectInfo.constructor(objectArg);
            objectArgOk = true;
        } catch (e) {
            objectArgOk = false;
        }
    }

    if (!objectArgOk)
        return @Promise.@reject(new @TypeError(`Argument 1 ('${objectInfo.argName}') to RTCPeerConnection.${functionName} must be an instance of ${objectInfo.argType}`));

    if (!@webRTCLegacyAPIEnabled() || argsCount === 1)
        return promiseMode(objectArg);

    // More than one argument: Legacy mode
    if (argsCount < 3)
        return @Promise.@reject(new @TypeError("Not enough arguments"));

    const successCallback = args[1];
    const errorCallback = args[2];

    if (typeof successCallback !== "function")
        return @Promise.@reject(new @TypeError(`Argument 2 ('successCallback') to RTCPeerConnection.${functionName} must be a function`));

    if (typeof errorCallback !== "function")
        return @Promise.@reject(new @TypeError(`Argument 3 ('errorCallback') to RTCPeerConnection.${functionName} must be a function`));

    return legacyMode(objectArg, successCallback, errorCallback);
}

function callbacksAndDictionaryOverload(args, functionName, promiseMode, legacyMode)
{
    "use strict";

    if (!@webRTCLegacyAPIEnabled() || args.length <= 1) {
        // Zero or one arguments: Promise mode
        const options = args[0];
        if (args.length && !@isDictionary(options))
            return @Promise.@reject(new @TypeError(`Argument 1 ('options') to RTCPeerConnection.${functionName} must be a dictionary`));

        return promiseMode(options);
    }

    // More than one argument: Legacy mode
    const successCallback = args[0];
    const errorCallback = args[1];
    const options = args[2];

    if (typeof successCallback !== "function")
        return @Promise.@reject(new @TypeError(`Argument 1 ('successCallback') to RTCPeerConnection.${functionName} must be a function`));

    if (typeof errorCallback !== "function")
        return @Promise.@reject(new @TypeError(`Argument 2 ('errorCallback') to RTCPeerConnection.${functionName} must be a function`));

    if (args.length > 2 && !@isDictionary(options))
        return @Promise.@reject(new @TypeError(`Argument 3 ('options') to RTCPeerConnection.${functionName} must be a dictionary`));

    return legacyMode(successCallback, errorCallback, args[2]);
}

function isRTCPeerConnection(connection)
{
    "use strict";

    return @isObject(connection) && !!connection.@operations;
}
