<!DOCTYPE html>
<!--

 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.

-->


<html>
  <head>
    <meta name="viewport" content="width=device-width,height=device-height,user-scalable=no,maximum-scale=1.0,initial-scale=1.0" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <!-- ISO-8859-1 -->
    <title>Cordova Mobile Spec</title>
    <link rel="stylesheet" href="../master.css" type="text/css" media="screen" title="no title" charset="utf-8">
    <script src="../cordova-incl.js"></script>
    <script src="setImmediate.js"></script>
<script>
    var exec = cordova.require('cordova/exec'),
        appLogElem = null,
        deviceReady = false,
        inProgress = false;

    function appLog(message) {
        if (!appLogElem) {
            appLogElem = document.getElementById('app-logs');
        }
        appLogElem.innerText += message + '\n';
        if (window.console) {
            console.log(message);
        }
    }

    function clearLogs() {
        appLogElem.innerHTML = '';
    }

    function updateUi(val) {
        inProgress = val;
        var goBtn = document.getElementById('go-btn');
        goBtn.textContent = inProgress ? 'Stop' : 'Start';
    }

    function benchExec() {
        updateUi(!inProgress);
        if (!inProgress) {
            return;
        }
        var echo = cordova.echo,
            startTime = +new Date,
            callCount = 0,
            elapsedMs,
            lastReportMs = 0,
            durationMs = parseInt(document.getElementById('test-duration').value, 10) * 1000,
            asyncEcho = document.getElementById('async-echo').checked,
            useSetTimeout = document.getElementById('use-setTimeout').checked,
            jsToNativeMode = document.getElementById('js-native-modes').value,
            nativeToJsMode = document.getElementById('native-js-modes').value,
            payloadSize = +document.getElementById('payload-size').value,
            soFarEl = document.getElementById('so-far'),
            payload = new Array(payloadSize * 10 + 1).join('012\n\n 6789');

        function reportProgress() {
            var callsPerSecond = String(callCount * 1000 / elapsedMs).slice(0, 6);
            soFarEl.textContent = callsPerSecond + ' ops';
            appLog('Calls per second: ' + callsPerSecond);
        }
        function win(result) {
            callCount++;
            if (result != payload) {
                appLog('Wrong echo data!');
                updateUi(false);
            }
            elapsedMs = new Date - startTime;
            if (inProgress && elapsedMs < durationMs) {
                if (elapsedMs - lastReportMs > 1000) {
                    reportProgress();
                    lastReportMs = elapsedMs;
                }
                if (useSetTimeout) {
                    setImmediate(echoMessage);
                } else {
                    echoMessage();
                }
            } else {
                reportProgress();
                updateUi(false);
            }
        }
        function fail() {
            appLog('Call failed!');
        }
        function echoMessage() {
            echo(win, fail, payload, asyncEcho);
        }

        var logMsg = 'Started exec benchmark with setTimeout: ' + useSetTimeout + ' asyncEcho: ' + asyncEcho + ' payload length: ' + payload.length;
        if (jsToNativeMode) {
            exec.setJsToNativeBridgeMode(+jsToNativeMode);
            logMsg += ' jsToNativeMode: ' + jsToNativeMode;
        }
        if (nativeToJsMode) {
            exec.setNativeToJsBridgeMode(+nativeToJsMode);
            logMsg += ' nativeToJsMode: ' + nativeToJsMode;
        }
        appLog(logMsg);
        echoMessage();
        setTimeout(function() {
            if (!callCount) {
                alert('Echo plugin did not respond');
            }
        }, 500);
    }

    function configureDragMe() {
        var dragMeEl = document.getElementById('drag-me');
        dragMeEl.ontouchmove = function(e) {
            e.preventDefault();
            var touch = e.touches[0];
            dragMeEl.style.left = touch.pageX - 50 + 'px';
            dragMeEl.style.top = touch.pageY - 50 + 'px';
        }
    }
    function configure() {
        function configureModes(elemId, modes) {
            var selectElem = document.getElementById(elemId);
            for (var modeName in modes) {
                var optionElem = document.createElement('option');
                optionElem.value = modes[modeName];
                optionElem.innerText = modeName;
                selectElem.appendChild(optionElem);
            }
            selectElem.parentNode.style.display = 'block';
        }
        if (exec.jsToNativeModes) {
            configureModes('js-native-modes', exec.jsToNativeModes);
        }
        if (exec.nativeToJsModes) {
            configureModes('native-js-modes', exec.nativeToJsModes);
        }
        configureDragMe();
    }


    document.addEventListener("deviceready", function() {
        deviceReady = true;
        appLog("Device="+device.platform+" "+device.version);
        configure();
    }, false);

    window.onload = function() {
        window.setTimeout(function() {
            if (!deviceReady) {
                alert("Error: Cordova did not initialize.  Demo will not run correctly.");
            }
        }, 1000);
    };

</script>

  </head>
  <body id="stage" class="theme">
    <h1>exec() Benchmark</h1>
    Before running on Android, set the following constants in NativeToJsMessagingBridge:
    <ul>
      <li>ENABLE_LOCATION_CHANGE_EXEC_MODE = true
      <li>DISABLE_EXEC_CHAINING = true
    </ul>
    As of iOS 7.0.2, Andrew found that the iframe bridge is still the fastest on iOS.
    <fieldset>
        <legend>Settings</legend>
        <label>Test Duration: <select id="test-duration"><option>1 Second</option><option>3 Seconds</option><option>10 seconds</option></select><br></label>
        <label style="display:none">JS-&gt;Native Bridge Mode: <select id="js-native-modes"></select><br></label>
        <label style="display:none">Native-&gt;JS Bridge Mode: <select id="native-js-modes"></select><br></label>
        <label><input type="checkbox" id="use-setTimeout"> Force async JS-&gt;Native (avoids evalAndFetch optimization on iOS)</label><br>
        <label><input type="checkbox" id="async-echo"> Force async Native-&gt;JS</label><br>
        <label>Payload size (in 100s of bytes) <input id="payload-size" value="5" style="width:100px"></label><br>
        <button id="go-btn" onclick="benchExec()">Start</button><br>
    </fieldset>
    <div>some text.<br>
        <div style="position:absolute;height:100px;background:red;width:100px;left:250px;top:50px;z-index:5" id="drag-me">Drag Me<div id="so-far"></div></div>
        <input value="dummy input"> text box to see if focus is lost by bridge or if there is typing lag.
    </div>
    <h2>&nbsp</h2><a href="javascript:" class="backBtn" onclick="backHome();">Back</a><br>
    <div>Results: <a href="javascript:clearLogs();">Clear</a></div>
    <pre id="app-logs" style="white-space:pre-wrap;line-height:initial; margin-bottom:500px"></pre>
    You've reached the bottom.
  </body>
</html>
