// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

(function(global, utils) {

"use strict";

%CheckIsBootstrapping();

// -----------------------------------------------------------------------
// Imports

var arrayIterationKindSymbol =
    utils.ImportNow("array_iteration_kind_symbol");
var arrayIteratorNextIndexSymbol =
    utils.ImportNow("array_iterator_next_symbol");
var arrayIteratorObjectSymbol =
    utils.ImportNow("array_iterator_object_symbol");
var GlobalArray = global.Array;
var IteratorPrototype = utils.ImportNow("IteratorPrototype");
var iteratorSymbol = utils.ImportNow("iterator_symbol");
var MakeTypeError;
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
var GlobalTypedArray = %object_get_prototype_of(global.Uint8Array);

utils.Import(function(from) {
  MakeTypeError = from.MakeTypeError;
})

// -----------------------------------------------------------------------

function ArrayIterator() {}


// TODO(wingo): Update section numbers when ES6 has stabilized.  The
// section numbers below are already out of date as of the May 2014
// draft.


// 15.4.5.1 CreateArrayIterator Abstract Operation
function CreateArrayIterator(array, kind) {
  var object = TO_OBJECT(array);
  var iterator = new ArrayIterator;
  SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
  SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
  SET_PRIVATE(iterator, arrayIterationKindSymbol, kind);
  return iterator;
}


// 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]
function ArrayIteratorIterator() {
    return this;
}


// ES6 section 22.1.5.2.1 %ArrayIteratorPrototype%.next( )
function ArrayIteratorNext() {
  var iterator = this;
  var value = UNDEFINED;
  var done = true;

  if (!IS_RECEIVER(iterator) ||
      !HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
    throw MakeTypeError(kIncompatibleMethodReceiver,
                        'Array Iterator.prototype.next', this);
  }

  var array = GET_PRIVATE(iterator, arrayIteratorObjectSymbol);
  if (!IS_UNDEFINED(array)) {
    var index = GET_PRIVATE(iterator, arrayIteratorNextIndexSymbol);
    var itemKind = GET_PRIVATE(iterator, arrayIterationKindSymbol);
    var length = TO_UINT32(array.length);

    // "sparse" is never used.

    if (index >= length) {
      SET_PRIVATE(iterator, arrayIteratorObjectSymbol, UNDEFINED);
    } else {
      SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);

      if (itemKind == ITERATOR_KIND_VALUES) {
        value = array[index];
      } else if (itemKind == ITERATOR_KIND_ENTRIES) {
        value = [index, array[index]];
      } else {
        value = index;
      }
      done = false;
    }
  }

  return %_CreateIterResultObject(value, done);
}


function ArrayEntries() {
  return CreateArrayIterator(this, ITERATOR_KIND_ENTRIES);
}


function ArrayValues() {
  return CreateArrayIterator(this, ITERATOR_KIND_VALUES);
}


function ArrayKeys() {
  return CreateArrayIterator(this, ITERATOR_KIND_KEYS);
}

// TODO(littledan): Check for detached TypedArray in these three methods
function TypedArrayEntries() {
  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
  return %_Call(ArrayEntries, this);
}


function TypedArrayValues() {
  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
  return %_Call(ArrayValues, this);
}


function TypedArrayKeys() {
  if (!IS_TYPEDARRAY(this)) throw MakeTypeError(kNotTypedArray);
  return %_Call(ArrayKeys, this);
}


%FunctionSetPrototype(ArrayIterator, {__proto__: IteratorPrototype});
%FunctionSetInstanceClassName(ArrayIterator, 'Array Iterator');

utils.InstallFunctions(ArrayIterator.prototype, DONT_ENUM, [
  'next', ArrayIteratorNext
]);
utils.SetFunctionName(ArrayIteratorIterator, iteratorSymbol);
%AddNamedProperty(ArrayIterator.prototype, toStringTagSymbol,
                  "Array Iterator", READ_ONLY | DONT_ENUM);

utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
  // No 'values' since it breaks webcompat: http://crbug.com/409858
  'entries', ArrayEntries,
  'keys', ArrayKeys
]);

// TODO(adam): Remove this call once 'values' is in the above
// InstallFunctions block, as it'll be redundant.
utils.SetFunctionName(ArrayValues, 'values');

%AddNamedProperty(GlobalArray.prototype, iteratorSymbol, ArrayValues,
                  DONT_ENUM);

utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [
  'entries', TypedArrayEntries,
  'keys', TypedArrayKeys,
  'values', TypedArrayValues
]);
%AddNamedProperty(GlobalTypedArray.prototype,
                  iteratorSymbol, TypedArrayValues, DONT_ENUM);

// -------------------------------------------------------------------
// Exports

utils.Export(function(to) {
  to.ArrayValues = ArrayValues;
});

%InstallToContext(["array_values_iterator", ArrayValues]);

})
