﻿/*
 *
 * 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.
 *
*/

exports.defineAutoTests = function () {
    var isWindows = (cordova.platformId === "windows") || (cordova.platformId === "windows8"),
     // Checking existence of accelerometer for windows platform 
     // Assumed that accelerometer always exists on other platforms. Extend 
     // condition to support accelerometer check on other platforms
     isAccelExist = isWindows ? Windows.Devices.Sensors.Accelerometer.getDefault() !== null : true;

  describe('Accelerometer (navigator.accelerometer)', function () {
    var fail = function(done) {
      expect(true).toBe(false);
      done();
    };

    // This timeout is here to lessen the load on native accelerometer
    // intensive use of which can lead to occasional test failures
    afterEach(function(done) {
      setTimeout(function() {
        done();
      }, 100);
    });

    it("accelerometer.spec.1 should exist", function () {
      expect(navigator.accelerometer).toBeDefined();
    });

    describe("getCurrentAcceleration", function() {
      it("accelerometer.spec.2 should exist", function() {
        expect(typeof navigator.accelerometer.getCurrentAcceleration).toBeDefined();
        expect(typeof navigator.accelerometer.getCurrentAcceleration == 'function').toBe(true);
      });

      it("accelerometer.spec.3 success callback should be called with an Acceleration object", function(done) {
        // skip the test if Accelerometer doesn't exist on this device
        if (!isAccelExist) {
          pending();
        }
        var win = function(a) {
          expect(a).toBeDefined();
          expect(a.x).toBeDefined();
          expect(typeof a.x == 'number').toBe(true);
          expect(a.y).toBeDefined();
          expect(typeof a.y == 'number').toBe(true);
          expect(a.z).toBeDefined();
          expect(typeof a.z == 'number').toBe(true);
          expect(a.timestamp).toBeDefined();
          expect(typeof a.timestamp).toBe('number');
          done();
        };

        var onError = function(err){
            console.log(err);
            console.log("Skipping gyroscope tests, marking all as pending.");
            isAccelExist = false;
            expect(true).toBe(true);
            done();
         }

        navigator.accelerometer.getCurrentAcceleration(win, onError);
      });

      it("accelerometer.spec.4 success callback Acceleration object should have (reasonable) values for x, y and z expressed in m/s^2", function(done) {
        // skip the test if Accelerometer doesn't exist on this device
        if (!isAccelExist) {
          pending();
        }
        var reasonableThreshold = 15;
        var win = function(a) {
          expect(a.x).toBeLessThan(reasonableThreshold);
          expect(a.x).toBeGreaterThan(reasonableThreshold * -1);
          expect(a.y).toBeLessThan(reasonableThreshold);
          expect(a.y).toBeGreaterThan(reasonableThreshold * -1);
          expect(a.z).toBeLessThan(reasonableThreshold);
          expect(a.z).toBeGreaterThan(reasonableThreshold * -1);
          done()
        };

        navigator.accelerometer.getCurrentAcceleration(win, fail.bind(null,done));
      });

      it("accelerometer.spec.5 success callback Acceleration object should return a recent timestamp", function(done) {
        // skip the test if Accelerometer doesn't exist on this device
        if (!isAccelExist) {
          pending();
        }
        var veryRecently = (new Date()).getTime();
        // Need to check that dates returned are not vastly greater than a recent time stamp.
        // In case the timestamps returned are ridiculously high
        var reasonableTimeLimit = veryRecently + 5000; // 5 seconds from now
        var win = function(a) {
          expect(a.timestamp).toBeGreaterThan(veryRecently);
          expect(a.timestamp).toBeLessThan(reasonableTimeLimit);
          done();
        };

        navigator.accelerometer.getCurrentAcceleration(win, fail.bind(null,done));
      });
    });

    describe("watchAcceleration", function() {
      var id;

      afterEach(function() {
          navigator.accelerometer.clearWatch(id);
      });

      it("accelerometer.spec.6 should exist", function() {
          expect(navigator.accelerometer.watchAcceleration).toBeDefined();
          expect(typeof navigator.accelerometer.watchAcceleration == 'function').toBe(true);
      });

      it("accelerometer.spec.7 success callback should be called with an Acceleration object", function(done) {
        // skip the test if Accelerometer doesn't exist on this device
        if (!isAccelExist) {
          pending();
        }
        var win = function(a) {
          expect(a).toBeDefined();
          expect(a.x).toBeDefined();
          expect(typeof a.x == 'number').toBe(true);
          expect(a.y).toBeDefined();
          expect(typeof a.y == 'number').toBe(true);
          expect(a.z).toBeDefined();
          expect(typeof a.z == 'number').toBe(true);
          expect(a.timestamp).toBeDefined();
          expect(typeof a.timestamp).toBe('number');
          done();
        };

        id = navigator.accelerometer.watchAcceleration(win, fail.bind(null,done), {frequency:100});
      });

        it("accelerometer.spec.8 success callback Acceleration object should have (reasonable) values for x, y and z expressed in m/s^2", function(done) {
          // skip the test if Accelerometer doesn't exist on this device
          if (!isAccelExist) {
            pending();
          }
          var reasonableThreshold = 15;
          var win = function(a) {
            expect(a.x).toBeLessThan(reasonableThreshold);
            expect(a.x).toBeGreaterThan(reasonableThreshold * -1);
            expect(a.y).toBeLessThan(reasonableThreshold);
            expect(a.y).toBeGreaterThan(reasonableThreshold * -1);
            expect(a.z).toBeLessThan(reasonableThreshold);
            expect(a.z).toBeGreaterThan(reasonableThreshold * -1);
            done();
          };

          id = navigator.accelerometer.watchAcceleration(win, fail.bind(null,done), {frequency:100});
        });

        it("accelerometer.spec.9 success callback Acceleration object should return a recent timestamp", function(done) {
          // skip the test if Accelerometer doesn't exist on this device
          if (!isAccelExist) {
            pending();
          }
          var veryRecently = (new Date()).getTime();
          // Need to check that dates returned are not vastly greater than a recent time stamp.
          // In case the timestamps returned are ridiculously high
          var reasonableTimeLimit = veryRecently + 5000; // 5 seconds from now
          var win = function(a) {
            expect(a.timestamp).toBeGreaterThan(veryRecently);
            expect(a.timestamp).toBeLessThan(reasonableTimeLimit);
            done();
          };

          id = navigator.accelerometer.watchAcceleration(win, fail.bind(null,done), {frequency:100});
        });

        it("accelerometer.spec.12 success callback should be preserved and called several times", function (done) {
            // skip the test if Accelerometer doesn't exist on this device
            if (!isAccelExist) {
              pending();
            }
            var callbacksCallCount = 0,
                callbacksCallTestCount = 3;

            var win = function (a) {
                if (callbacksCallCount++ < callbacksCallTestCount) return;
                expect(typeof a).toBe('object');
                done();
            };

            id = navigator.accelerometer.watchAcceleration(win, fail.bind(null, done), { frequency: 100 });
        });
    });

    describe("clearWatch", function() {
      it("accelerometer.spec.10 should exist", function() {
          expect(navigator.accelerometer.clearWatch).toBeDefined();
          expect(typeof navigator.accelerometer.clearWatch == 'function').toBe(true);
      });

      it("accelerometer.spec.11 should clear an existing watch", function(done) {
          // skip the test if Accelerometer doesn't exist on this device
          if (!isAccelExist) {
              pending();
          }
          var id;

          // expect win to get called exactly once
          var win = function(a) {
            // clear watch on first call
            navigator.accelerometer.clearWatch(id);
            // if win isn't called again in 201 ms we assume success
            var tid = setTimeout(function() {
              expect(true).toBe(true);
              done();
            }, 101);
            // if win is called again, clear the timeout and fail the test
            win = function() {
              clearTimeout(tid);
              fail(done);
            }
          };

          // wrap the success call in a closure since the value of win changes between calls
          id = navigator.accelerometer.watchAcceleration(function() { win(); }, fail.bind(null, done), {frequency:100});
      });
    });
  });
};

/******************************************************************************/
/******************************************************************************/
/******************************************************************************/

exports.defineManualTests = function (contentEl, createActionButton) {
    function roundNumber(num) {
        var dec = 3;
        var result = Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
        return result;
    }

    var watchAccelId = null;

    /**
     * Start watching acceleration
     */
    var watchAccel = function () {
        console.log("watchAccel()");

        // Success callback
        var success = function (a) {
            document.getElementById('x').innerHTML = roundNumber(a.x);
            document.getElementById('y').innerHTML = roundNumber(a.y);
            document.getElementById('z').innerHTML = roundNumber(a.z);
        };

        // Fail callback
        var fail = function (e) {
            console.log("watchAccel fail callback with error code " + e);
            stopAccel();
            setAccelStatus(e);
        };

        // Update acceleration every 1 sec
        var opt = {};
        opt.frequency = 1000;
        watchAccelId = navigator.accelerometer.watchAcceleration(success, fail, opt);

        setAccelStatus("Running");
    };

    /**
     * Stop watching the acceleration
     */
    var stopAccel = function () {
        console.log("stopAccel()");
        setAccelStatus("Stopped");
        if (watchAccelId) {
            navigator.accelerometer.clearWatch(watchAccelId);
            watchAccelId = null;
        }
    };

    /**
     * Get current acceleration
     */
    var getAccel = function () {
        console.log("getAccel()");

        // Stop accel if running
        stopAccel();

        // Success callback
        var success = function (a) {
            document.getElementById('x').innerHTML = roundNumber(a.x);
            document.getElementById('y').innerHTML = roundNumber(a.y);
            document.getElementById('z').innerHTML = roundNumber(a.z);
            console.log("getAccel success callback");
        };

        // Fail callback
        var fail = function (e) {
            console.log("getAccel fail callback with error code " + e);
            setAccelStatus(e);
        };

        // Make call
        var opt = {};
        navigator.accelerometer.getCurrentAcceleration(success, fail, opt);
    };

    /**
     * Set accelerometer status
     */
    var setAccelStatus = function (status) {
        document.getElementById('accel_status').innerHTML = status;
    };

    /******************************************************************************/

    var accelerometer_tests = '<div id="getAcceleration"></div>' +
        'Expected result: Will update the status box with X, Y, and Z values when pressed. Status will read "Stopped"' +
        '<p/> <div id="watchAcceleration"></div>' +
        'Expected result: When pressed, will start a watch on the accelerometer and update X,Y,Z values when movement is sensed. Status will read "Running"' +
        '<p/> <div id="clearAcceleration"></div>' +
        'Expected result: Will clear the accelerometer watch, so X,Y,Z values will no longer be updated. Status will read "Stopped"';

    contentEl.innerHTML = '<div id="info">' +
        'Status: <span id="accel_status">Stopped</span>' +
        '<table width="100%">' +
        '<tr><td width="20%">X:</td><td id="x"> </td></tr>' +
        '<tr><td width="20%">Y:</td><td id="y"> </td></tr>' +
        '<tr><td width="20%">Z:</td><td id="z"> </td></tr>' +
        '</table></div>' +
        accelerometer_tests;

    createActionButton('Get Acceleration', function () {
        getAccel();
    }, 'getAcceleration');

    createActionButton('Start Watch', function () {
        watchAccel();
    }, 'watchAcceleration');

    createActionButton('Clear Watch', function () {
        stopAccel();
    }, 'clearAcceleration');
};
