/*
 *
 * 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 Windows, WinJS, Vibration */

function checkReqs (actionName, fail) {
    if (!(Windows.Phone && Windows.Phone.Devices && Windows.Phone.Devices.Notification && Windows.Phone.Devices.Notification.VibrationDevice) && WinJS.Utilities.isPhone !== true) {
        fail(actionName + ' is unsupported by this platform.');
        return false;
    }

    return true;
}

function tryDoAction (actionName, success, fail, args, action) {
    try {
        if (checkReqs(actionName, fail) !== true) {
            return;
        }

        action(args);
        success();
    } catch (e) {
        fail('Error occured while trying to ' + actionName + ': ' + e);
    }
}

/**
 * @typedef patternParsingResult
 * @type {Object}
 * @property {Array} result.parsed - Array with parsed integers
 * @property {Boolean} result.passed - false in case of parsing error
 * @property {*} result.failedItem - The item, which could not be parsed
 */

/**
 * Tries to convert pattern values to int
 * @param  {Array} pattern Array of delays
 * @returns {patternParsingResult} result
 */
function tryParsePatternValues (pattern) {
    var passed = true;
    var failedItem;

    pattern = pattern.map(function (item) {
        var num = parseInt(item, 10);
        if (isNaN(num)) {
            failedItem = item;
            passed = false;
        }

        return num;
    });

    return {
        parsed: pattern,
        passed: passed,
        failedItem: failedItem
    };
}

/**
 * @typedef checkPatternReqsResult
 * @type {Object}
 * @property {Array} result.patternParsingResult - Array with parsed integers
 * @property {Boolean} result.passed - true if all params are OK
 */

/**
 * Checks params for vibrateWithPattern function
 * @return {checkPatternReqsResult}
 */
function checkPatternReqs (args, fail) {
    var patternParsingResult = tryParsePatternValues(args[0]);
    var repeat = args[1];
    var passed = true;
    var errMsg = '';

    if (!patternParsingResult.passed) {
        errMsg += 'Could not parse ' + patternParsingResult.failedItem + ' in the vibration pattern';
        passed = false;
    }

    if (repeat !== -1 && (repeat < 0 || repeat > args[0].length - 1)) {
        errMsg += '\nrepeat parameter is out of range: ' + repeat;
        passed = false;
    }

    if (!passed) {
        console.error(errMsg);
        if (fail) {
            fail(errMsg);
        }
    }

    return {
        passed: passed,
        patternParsingResult: patternParsingResult
    };
}

/**
 * vibrateWithPattern with `repeat` support
 * @param  {Array} patternArr Full pattern array
 * @param  {Boolean} shouldRepeat Indication on whether the vibration should be cycled
 * @param  {Function} fail Fail callback
 * @param  {Array} patternCycle Cycled part of the pattern array
 * @return {Promise} Promise chaining single vibrate/pause actions
 */
function vibratePattern (patternArr, shouldRepeat, fail, patternCycle) {
    return patternArr.reduce(function (previousValue, currentValue, index) {
        if (index % 2 === 0) {
            return previousValue.then(function () {
                module.exports.vibrate(function () { }, function (err) {
                    console.error(err);
                    if (fail) {
                        fail(err);
                    }
                }, [currentValue]);

                if (index === patternArr.length - 1 && shouldRepeat) {
                    return WinJS.Promise.timeout(currentValue).then(function () {
                        return vibratePattern(patternCycle, true, fail, patternCycle);
                    });
                } else {
                    return WinJS.Promise.timeout(currentValue);
                }
            });
        } else {
            return previousValue.then(function () {
                if (index === patternArr.length - 1 && shouldRepeat) {
                    return WinJS.Promise.timeout(currentValue).then(function () {
                        return vibratePattern(patternCycle, true, fail, patternCycle);
                    });
                } else {
                    return WinJS.Promise.timeout(currentValue);
                }
            });
        }
    }, WinJS.Promise.as());
}

var DEFAULT_DURATION = 200;
var patternChainPromise;

var VibrationDevice = (Windows.Phone && Windows.Phone.Devices && Windows.Phone.Devices.Notification && Windows.Phone.Devices.Notification.VibrationDevice && Windows.Phone.Devices.Notification.VibrationDevice);
if (VibrationDevice) {
    // Windows Phone 10 code paths
    module.exports = {
        vibrate: function (success, fail, args) {
            try {
                var duration = parseInt(args[0]);
                if (isNaN(duration)) {
                    duration = DEFAULT_DURATION;
                }
                VibrationDevice.getDefault().vibrate(duration);
                success();
            } catch (e) {
                fail(e);
            }
        },
        vibrateWithPattern: function (success, fail, args) {
            // Cancel current vibrations first
            module.exports.cancelVibration(function () {
                var checkReqsResult = checkPatternReqs(args, fail);
                if (!checkReqsResult.passed) {
                    return;
                }

                var pattern = checkReqsResult.patternParsingResult.parsed;
                var repeatFromIndex = args[1];
                var shouldRepeat = (repeatFromIndex !== -1);
                var patternCycle;

                if (shouldRepeat) {
                    patternCycle = pattern.slice(repeatFromIndex);
                }

                patternChainPromise = vibratePattern(pattern, shouldRepeat, fail, patternCycle);
            }, fail);
        },
        cancelVibration: function (success, fail, args) {
            try {
                if (patternChainPromise) {
                    patternChainPromise.cancel();
                }
                VibrationDevice.getDefault().cancel();
                if (success) {
                    success();
                }
            } catch (e) {
                if (fail) {
                    fail(e);
                }
            }
        }
    };
} else if (typeof Vibration !== 'undefined' && Vibration.Vibration) {
    // Windows Phone 8.1 code paths
    module.exports = {
        vibrate: function (success, fail, args) {
            tryDoAction('vibrate', success, fail, args, Vibration.Vibration.vibrate);
        },

        vibrateWithPattern: function (success, fail, args) {
            tryDoAction('vibrate', success, fail, [DEFAULT_DURATION], Vibration.Vibration.vibrate);
        },

        cancelVibration: function (success, fail, args) {
            tryDoAction('cancelVibration', success, fail, args, Vibration.Vibration.cancelVibration);
        }
    };
} else {
    // code paths where no vibration mechanism is present
    module.exports = {
        vibrate: function (success, fail) {
            if (fail) {
                fail('"vibrate" is unsupported by this device.');
            }
        },
        vibrateWithPattern: function (success, fail, args) {
            if (fail) {
                fail('"vibrateWithPattern" is unsupported by this device.');
            }
        },

        cancelVibration: function (success, fail, args) {
            if (success) {
                success();
            }
        }
    };
}

require('cordova/exec/proxy').add('Vibration', module.exports);
