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

/* global CompassError, CompassHeading */

exports.defineAutoTests = function () {
    var fail = function (done, message) {
        message = typeof message !== 'string' ? 'Forced failure: wrong callback called' : message;
        expect(true).toFailWithMessage(message);
        done();
    };
    var unexpectedFailure = 'Forced failure: error callback should not have been called';

    describe('Compass (navigator.compass)', function () {
        beforeEach(function () {
            jasmine.Expectation.addMatchers({
                toFailWithMessage: function () {
                    return {
                        compare: function (actual, customMessage) {
                            var pass = false;
                            if (customMessage === undefined) {
                                customMessage = 'Forced failure: wrong callback called';
                            }
                            return {
                                pass: pass,
                                message: customMessage
                            };
                        }
                    };
                }
            });
        });

        var isCompassAvailable = null;

        beforeEach(function (done) {
            if (isCompassAvailable === false) {
                // if we're already ensured that compass is not available, no need to check it again
                done();
            } else if (isCompassAvailable === null) {
                // Try to access compass device, and if it is not available
                // set hardwarefailure flag to mark some tests pending
                navigator.compass.getCurrentHeading(
                    function () {
                        isCompassAvailable = true;
                        done();
                    },
                    function (error) {
                        if (error.code === CompassError.COMPASS_NOT_SUPPORTED) {
                            isCompassAvailable = false;
                        }
                        done();
                    }
                );
            } else {
                // wait a little
                setTimeout(function () {
                    done();
                }, 200);
            }
        });

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

        it('compass.spec.2 should contain a getCurrentHeading function', function () {
            expect(navigator.compass.getCurrentHeading).toBeDefined();
            expect(typeof navigator.compass.getCurrentHeading === 'function').toBe(true);
        });

        it('compass.spec.3 getCurrentHeading success callback should be called with a Heading object', function (done) {
            if (!isCompassAvailable) {
                pending();
            }
            navigator.compass.getCurrentHeading(function (a) {
                expect(a instanceof CompassHeading).toBe(true);
                expect(a.magneticHeading).toBeDefined();
                expect(typeof a.magneticHeading === 'number').toBe(true);
                expect(a.trueHeading).not.toBe(undefined);
                expect(typeof a.trueHeading === 'number' || a.trueHeading === null).toBe(true);
                expect(a.headingAccuracy).not.toBe(undefined);
                expect(typeof a.headingAccuracy === 'number' || a.headingAccuracy === null).toBe(true);
                expect(typeof a.timestamp === 'number').toBe(true);
                done();
            }, fail.bind(null, done, unexpectedFailure));
        });

        it('compass.spec.4 should contain a watchHeading function', function () {
            expect(navigator.compass.watchHeading).toBeDefined();
            expect(typeof navigator.compass.watchHeading === 'function').toBe(true);
        });

        it('compass.spec.5 should contain a clearWatch function', function () {
            expect(navigator.compass.clearWatch).toBeDefined();
            expect(typeof navigator.compass.clearWatch === 'function').toBe(true);
        });

        describe('Compass Constants (window.CompassError)', function () {
            it('compass.spec.1 should exist', function () {
                expect(window.CompassError).toBeDefined();
                expect(window.CompassError.COMPASS_INTERNAL_ERR).toBe(0);
                expect(window.CompassError.COMPASS_NOT_SUPPORTED).toBe(20);
            });
        });

        describe('Compass Heading model (CompassHeading)', function () {
            it('compass.spec.1 should exist', function () {
                expect(CompassHeading).toBeDefined();
            });

            it('compass.spec.8 should be able to create a new CompassHeading instance with no parameters', function () {
                var h = new CompassHeading();
                expect(h).toBeDefined();
                expect(h.magneticHeading).toBeUndefined();
                expect(h.trueHeading).toBeUndefined();
                expect(h.headingAccuracy).toBeUndefined();
                expect(typeof h.timestamp === 'number').toBe(true);
            });

            it('compass.spec.9 should be able to create a new CompassHeading instance with parameters', function () {
                var h = new CompassHeading(1, 2, 3, 4);
                expect(h.magneticHeading).toBe(1);
                expect(h.trueHeading).toBe(2);
                expect(h.headingAccuracy).toBe(3);
                expect(h.timestamp.valueOf()).toBe(4);
                expect(typeof h.timestamp === 'number').toBe(true);
            });
        });

        describe('Compass watch heading', function () {
            it('compass.spec.10 watchCurrentHeading called with a Heading object', function (done) {
                if (!isCompassAvailable) {
                    pending();
                }

                var calledOnce = false;

                var watchId = navigator.compass.watchHeading(
                    function (a) {
                        expect(a instanceof CompassHeading).toBe(true);
                        expect(a.magneticHeading).toBeDefined();
                        expect(typeof a.magneticHeading === 'number').toBe(true);
                        expect(a.trueHeading).not.toBe(undefined);
                        expect(typeof a.trueHeading === 'number' || a.trueHeading === null).toBe(true);
                        expect(a.headingAccuracy).not.toBe(undefined);
                        expect(typeof a.headingAccuracy === 'number' || a.headingAccuracy === null).toBe(true);
                        expect(typeof a.timestamp === 'number').toBe(true);

                        if (calledOnce) {
                            navigator.compass.clearWatch(watchId);
                            done();
                        }

                        calledOnce = true;
                    },
                    function (compassError) {},
                    { frequency: 50 }
                );
            });

            it('compass.spec.11 the watch success callback should not be called once the watch is cleared', function (done) {
                if (!isCompassAvailable) {
                    pending();
                }

                var calledOnce = false;
                var watchCleared = false;

                var watchId = navigator.compass.watchHeading(
                    function (a) {
                        // Don't invoke this function if we have cleared the watch
                        expect(watchCleared).toBe(false);

                        if (calledOnce && !watchCleared) {
                            navigator.compass.clearWatch(watchId);
                            watchCleared = true;
                            setTimeout(function () {
                                done();
                            }, 1000);
                        }

                        calledOnce = true;
                    },
                    function (compassError) {},
                    { frequency: 50 }
                );
            });
        });
    });
};

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

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 watchCompassId = null;

    /**
     * Set compass status
     */
    function setCompassStatus (status) {
        document.getElementById('compass_status').innerHTML = status;
    }

    // Success callback for both watchHeading and getCurrentHeading
    function success (a) {
        var magneticHeading = document.getElementById('magneticHeading');
        var trueHeading = document.getElementById('trueHeading');
        var headingAccuracy = document.getElementById('headingAccuracy');
        var timestamp = document.getElementById('timestamp');

        magneticHeading.innerHTML = roundNumber(a.magneticHeading);
        trueHeading.innerHTML = roundNumber(a.trueHeading);
        headingAccuracy.innerHTML = a.headingAccuracy;
        timestamp.innerHTML = a.timestamp;
    }

    /**
     * Stop watching the acceleration
     */
    function stopCompass () {
        setCompassStatus('Stopped');
        if (watchCompassId) {
            navigator.compass.clearWatch(watchCompassId);
            watchCompassId = null;
        }
    }

    /**
     * Start watching compass
     */
    var watchCompass = function () {
        console.log('watchCompass()');

        // Fail callback
        var fail = function (e) {
            console.log('watchCompass fail callback with error: ' + JSON.stringify(e));
            stopCompass();
            setCompassStatus(e);
        };

        // Stop compass if running
        stopCompass();

        // Update heading every 1 sec
        var opt = {};
        opt.frequency = 1000;
        watchCompassId = navigator.compass.watchHeading(success, fail, opt);

        setCompassStatus('Running');
    };

    /**
     * Get current compass
     */
    var getCompass = function () {
        console.log('getCompass()');

        // Stop compass if running
        stopCompass();

        // Fail callback
        var fail = function (e) {
            console.log('getCompass fail callback with error: ' + JSON.stringify(e));
            setCompassStatus(e);
        };

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

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

    var orientation_tests =
        '<h3>iOS devices may bring up a calibration screen when initiating these tests</h3>' +
        '<div id="getCompass"></div>' +
        'Expected result: Will update the status box with current heading. Status will read "Stopped"' +
        '<p/> <div id="watchCompass"></div>' +
        'Expected result: When pressed, will start a watch on the compass and update the heading value when heading changes. Status will read "Running"' +
        '<p/> <div id="stopCompass"></div>' +
        'Expected result: Will clear the compass watch, so heading value will no longer be updated. Status will read "Stopped"';

    contentEl.innerHTML =
        '<div id="info"><b>Status: </b>' +
        '<span id="compass_status">Stopped</span>' +
        '<table width="100%">' +
        '<tr><td width="33%">Magnetic heading: <span id="magneticHeading"></span></td></tr>' +
        '<tr><td width="33%">True heading: <span id="trueHeading"></span></td></tr>' +
        '<tr><td width="33%">Heading accuracy: <span id="headingAccuracy"></span></td></tr>' +
        '<tr><td width="33%">Timestamp: <span id="timestamp"></span></td></tr>' +
        '</table></div>' +
        orientation_tests;

    createActionButton(
        'Get Compass',
        function () {
            getCompass();
        },
        'getCompass'
    );

    createActionButton(
        'Start Watching Compass',
        function () {
            watchCompass();
        },
        'watchCompass'
    );

    createActionButton(
        'Stop Watching Compass',
        function () {
            stopCompass();
        },
        'stopCompass'
    );
};
