/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

/**
 * Creates a gap bridge iframe used to notify the native code about queued
 * commands.
 */
var cordova = require('cordova'),
    channel = require('cordova/channel'),
    utils = require('cordova/utils'),
    base64 = require('cordova/base64'),
    // XHR mode does not work on iOS 4.2.
    // XHR mode's main advantage is working around a bug in -webkit-scroll, which
    // doesn't exist only on iOS 5.x devices.
    // IFRAME_NAV is the fastest.
    // IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
    jsToNativeModes = {
        IFRAME_NAV: 0,
        XHR_NO_PAYLOAD: 1,
        XHR_WITH_PAYLOAD: 2,
        XHR_OPTIONAL_PAYLOAD: 3,
        IFRAME_HASH_NO_PAYLOAD: 4,
        // Bundling the payload turns out to be slower. Probably since it has to be URI encoded / decoded.
        IFRAME_HASH_WITH_PAYLOAD: 5
    },
    bridgeMode,
    execIframe,
    execHashIframe,
    hashToggle = 1,
    execXhr,
    requestCount = 0,
    vcHeaderValue = null,
    commandQueue = [], // Contains pending JS->Native messages.
    isInContextOfEvalJs = 0;

function createExecIframe() {
    var iframe = document.createElement("iframe");
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    return iframe;
}

function createHashIframe() {
    var ret = createExecIframe();
    // Hash changes don't work on about:blank, so switch it to file:///.
    ret.contentWindow.history.replaceState(null, null, 'file:///#');
    return ret;
}

function shouldBundleCommandJson() {
    if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
        return true;
    }
    if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
        var payloadLength = 0;
        for (var i = 0; i < commandQueue.length; ++i) {
            payloadLength += commandQueue[i].length;
        }
        // The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
        return payloadLength < 4500;
    }
    return false;
}

function massageArgsJsToNative(args) {
    if (!args || utils.typeName(args) != 'Array') {
        return args;
    }
    var ret = [];
    args.forEach(function(arg, i) {
        if (utils.typeName(arg) == 'ArrayBuffer') {
            ret.push({
                'CDVType': 'ArrayBuffer',
                'data': base64.fromArrayBuffer(arg)
            });
        } else {
            ret.push(arg);
        }
    });
    return ret;
}

function massageMessageNativeToJs(message) {
    if (message.CDVType == 'ArrayBuffer') {
        var stringToArrayBuffer = function(str) {
            var ret = new Uint8Array(str.length);
            for (var i = 0; i < str.length; i++) {
                ret[i] = str.charCodeAt(i);
            }
            return ret.buffer;
        };
        var base64ToArrayBuffer = function(b64) {
            return stringToArrayBuffer(atob(b64));
        };
        message = base64ToArrayBuffer(message.data);
    }
    return message;
}

function convertMessageToArgsNativeToJs(message) {
    var args = [];
    if (!message || !message.hasOwnProperty('CDVType')) {
        args.push(message);
    } else if (message.CDVType == 'MultiPart') {
        message.messages.forEach(function(e) {
            args.push(massageMessageNativeToJs(e));
        });
    } else {
        args.push(massageMessageNativeToJs(message));
    }
    return args;
}

function iOSExec() {
    // Use XHR for iOS 5 to work around a bug in -webkit-scroll.
    // Use IFRAME_NAV elsewhere since it's faster and XHR bridge
    // seems to have bugs in newer OS's (CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134)
    if (bridgeMode === undefined) {
        if (navigator.userAgent) {
            bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD;
		} else {
            bridgeMode = jsToNativeModes.IFRAME_NAV;
        }
    }
    
    var successCallback, failCallback, service, action, actionArgs, splitCommand;
    var callbackId = null;
    if (typeof arguments[0] !== "string") {
        // FORMAT ONE
        successCallback = arguments[0];
        failCallback = arguments[1];
        service = arguments[2];
        action = arguments[3];
        actionArgs = arguments[4];

        // Since we need to maintain backwards compatibility, we have to pass
        // an invalid callbackId even if no callback was provided since plugins
        // will be expecting it. The Cordova.exec() implementation allocates
        // an invalid callbackId and passes it even if no callbacks were given.
        callbackId = 'INVALID';
    } else {
        // FORMAT TWO, REMOVED
        try {
            splitCommand = arguments[0].split(".");
            action = splitCommand.pop();
            service = splitCommand.join(".");
            actionArgs = Array.prototype.splice.call(arguments, 1);

            console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
                       "cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
            );
            return;
        } catch (e) {}
    }

    // If actionArgs is not provided, default to an empty array
    actionArgs = actionArgs || [];

    // Register the callbacks and add the callbackId to the positional
    // arguments if given.
    if (successCallback || failCallback) {
        callbackId = service + cordova.callbackId++;
        cordova.callbacks[callbackId] =
            {success:successCallback, fail:failCallback};
    }

    actionArgs = massageArgsJsToNative(actionArgs);

    var command = [callbackId, service, action, actionArgs];

    // Stringify and queue the command. We stringify to command now to
    // effectively clone the command arguments in case they are mutated before
    // the command is executed.
    commandQueue.push(JSON.stringify(command));

    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
    // then the queue will be flushed when it returns; no need for a poke.
    // Also, if there is already a command in the queue, then we've already
    // poked the native side, so there is no reason to do so again.
    if (!isInContextOfEvalJs && commandQueue.length == 1) {
        switch (bridgeMode) {
        case jsToNativeModes.XHR_NO_PAYLOAD:
        case jsToNativeModes.XHR_WITH_PAYLOAD:
        case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
            pokeNativeViaXhr();
            break;
        default: // iframe-based.
            pokeNativeViaIframe();
        }
    }
}

function pokeNativeViaXhr() {
    // This prevents sending an XHR when there is already one being sent.
    // This should happen only in rare circumstances (refer to unit tests).
    if (execXhr && execXhr.readyState != 4) {
        execXhr = null;
    }
    // Re-using the XHR improves exec() performance by about 10%.
    execXhr = execXhr || new XMLHttpRequest();
    // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
    // For some reason it still doesn't work though...
    // Add a timestamp to the query param to prevent caching.
    execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
    if (!vcHeaderValue) {
        vcHeaderValue = /.*\((.*)\)/.exec(navigator.userAgent)[1];
    }
    execXhr.setRequestHeader('vc', vcHeaderValue);
    execXhr.setRequestHeader('rc', ++requestCount);
    if (shouldBundleCommandJson()) {
        execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
    }
    execXhr.send(null);
}

function pokeNativeViaIframe() {
    // CB-5488 - Don't attempt to create iframe before document.body is available.
    if (!document.body) {
        setTimeout(pokeNativeViaIframe);
        return;
    }
    if (bridgeMode === jsToNativeModes.IFRAME_HASH_NO_PAYLOAD || bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
        execHashIframe = execHashIframe || createHashIframe();
        // Check if they've removed it from the DOM, and put it back if so.
        if (!execHashIframe.contentWindow) {
            execHashIframe = createHashIframe();
        }
        // The delegate method is called only when the hash changes, so toggle it back and forth.
        hashToggle = hashToggle ^ 3;
        var hashValue = '%0' + hashToggle;
        if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
            hashValue += iOSExec.nativeFetchMessages();
        }
        execHashIframe.contentWindow.location.hash = hashValue;
    } else {
        execIframe = execIframe || createExecIframe();
        // Check if they've removed it from the DOM, and put it back if so.
        if (!execIframe.contentWindow) {
            execIframe = createExecIframe();
        }
        execIframe.src = "gap://ready";
    }
}

iOSExec.jsToNativeModes = jsToNativeModes;

iOSExec.setJsToNativeBridgeMode = function(mode) {
    // Remove the iFrame since it may be no longer required, and its existence
    // can trigger browser bugs.
    // https://issues.apache.org/jira/browse/CB-593
    if (execIframe) {
        execIframe.parentNode.removeChild(execIframe);
        execIframe = null;
    }
    bridgeMode = mode;
};

iOSExec.nativeFetchMessages = function() {
    // Each entry in commandQueue is a JSON string already.
    if (!commandQueue.length) {
        return '';
    }
    var json = '[' + commandQueue.join(',') + ']';
    commandQueue.length = 0;
    return json;
};

iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
    return iOSExec.nativeEvalAndFetch(function() {
        var success = status === 0 || status === 1;
        var args = convertMessageToArgsNativeToJs(message);
        cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
    });
};

iOSExec.nativeEvalAndFetch = function(func) {
    // This shouldn't be nested, but better to be safe.
    isInContextOfEvalJs++;
    try {
        func();
        return iOSExec.nativeFetchMessages();
    } finally {
        isInContextOfEvalJs--;
    }
};

module.exports = iOSExec;
