'use strict';

var isDefined = require('../../common/internal/isDefined'),
    assertCallable = require('../../common/internal/assertCallable');

function arrayReduce(arr, fn, initialValue, fromRight) {
  var length = arr.length, count = 0, defined = isDefined(initialValue), result, index;
  assertCallable(fn);
  if (length == 0 && !defined) {
    throw new TypeError('Reduce called on empty array with no initial value');
  } else if (defined) {
    result = initialValue;
  } else {
    result = arr[fromRight ? length - 1 : count];
    count++;
  }
  while(count < length) {
    index = fromRight ? length - count - 1 : count;
    if (index in arr) {
      result = fn(result, arr[index], index, arr);
    }
    count++;
  }
  return result;
}

module.exports = arrayReduce;