<!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 type="text/javascript" charset="utf-8" src="../cordova.js"></script>      
    <script type="text/javascript" charset="utf-8" src="uubench.js"></script>
    <script type="text/javascript" charset="utf-8" src="licensecontents.js"></script>
<script>
    var exec = cordova.require('cordova/exec');
    var temp, pers, LICENSE_CONTENTS;
    function $(id) { return document.getElementById(id); }

    function copy_license(filesystem, callback) {
        filesystem.root.getFile("LICENSE", {create: true, exclusive: false}, function(entry) {
            entry.createWriter(function(writer) {
                writer.onwriteend = function(evt) {
                    callback();
                };
                writer.write(LICENSE_CONTENTS);
            }, function(err) {
                alert('Error creating LICENSE FileWriter');
            });
        }, function(err) {
            alert('Error copying LICENSE to a file system');
        });
    }

    var suite = new uubench.Suite({
        start:function() {
            $('loading').innerHTML = "BENCHMARKING IN PROGRESS...";
        },
        result: function(name, stats) {
            var secs = stats.elapsed/1000;
            var itspersec = stats.iterations / secs;
            $('table-results').innerHTML += '<tr><td>' + name + '</td><td>' + itspersec + ' per second.</td></tr>';
            console.log(name + ' bench complete.');
            results[name] = stats;
        },
        min: 2000, // each benchmark should run for at least 2000ms
        done:function() { 
            $('loading').innerHTML = "Benchmarks complete.";
        }
    });
    var results = {};

    document.addEventListener("deviceready", function() {
        deviceReady = true;
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "../LICENSE", true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) {
                if (xhr.responseText.length > 0) {
                    LICENSE_CONTENTS = xhr.responseText;
                } else {
                    alert('Some prereq XHR stuff to get license content failed mang.');
                }
                window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(p_fs) {
                    pers = p_fs;
                    copy_license(pers, function() {
                        window.requestFileSystem(LocalFileSystem.TEMPORARY, 0, function(t_fs) {
                            temp = t_fs;
                            copy_license(temp, function() {
                                setTimeout(bench, 250);
                            });
                        }, function(t_e) {
                            alert('Failed to get TEMPORARY File System');
                        });
                    });
                }, function(p_e) {
                    alert('Failed to get PERSISTENT File System');
                });
            }
        };
        xhr.send(null);
    });

    window.onload = function() {
        window.setTimeout(function() {
            if (!deviceReady) {
                alert("Error: Cordova did not initialize.  Demo will not run correctly.");
            }
        }, 1000);
    };
function bench() {
    suite.bench("Echo exec callbacks", function(next) {
        exec(function() {
            // win
            next();
        }, function() {
            // fail
            next();
        }, "Echo", "echo", ["test"]);
    });
    suite.bench("Echo exec invocations", function(next) {
        exec(function() {
            // win
        }, function() {
            // fail
        }, "Echo", "echo", ["test"]);
        next();
    });
    suite.bench("XHR to within-package 11kb asset.", function(next) {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "../LICENSE", true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4) {
                if (xhr.status == 200) {
                    next();
                } else {
                    alert('There was a problem during XHR file read!');
                }
            }
        };
        xhr.send(null);
    });
    if (temp) {
        suite.bench("Get contents of 11kb asset located on TEMPORARY File System using FileReader's readAsText method.", function(next) {
            temp.root.getFile("LICENSE", null, function(entry) {
                entry.file(function(file) {
                    var reader = new FileReader();
                    reader.onloadend = function(evt) {
                        next();
                    };
                    reader.readAsText(file);
                }, function(err) {
                    alert('Error getting File object from LICENSE file in TEMP FS.');
                });
            }, function(err) {
                alert('Error getting LICENSE file from root of TEMP FS.');
            });
        });
    }
    if (pers) {
        suite.bench("Get contents of 11kb asset located on PERSISTENT File System using FileReader's readAsText method.", function(next) {
            pers.root.getFile("LICENSE", null, function(entry) {
                entry.file(function(file) {
                    var reader = new FileReader();
                    reader.onloadend = function(evt) {
                        next();
                    };
                    reader.readAsText(file);
                }, function(err) {
                    alert('Error getting File object from LICENSE file in PERSISTENT FS.');
                });
            }, function(err) {
                alert('Error getting LICENSE file from root of PERSISTENT FS.');
            });
        });
    }
    suite.run();
}
</script>

  </head>
  <body>
    <h1>Auto-Benchmarks</h1>
    <h2 id="loading"></h2>
    <table>
        <thead style="font-weight:bold;text-align:center;">
            <tr>
                <td>Name</td>
                <td>Results</td>
            </tr>
        </thead>
        <tbody id="table-results">
        </tbody>
    </table>
  </body>
</html>      
