/* */ 
'use strict';
var $ = require("./$"),
    cof = require("./$.cof"),
    classof = cof.classof,
    assert = require("./$.assert"),
    assertObject = assert.obj,
    SYMBOL_ITERATOR = require("./$.wks")('iterator'),
    FF_ITERATOR = '@@iterator',
    Iterators = require("./$.shared")('iterators'),
    IteratorPrototype = {};
setIterator(IteratorPrototype, $.that);
function setIterator(O, value) {
  $.hide(O, SYMBOL_ITERATOR, value);
  if (FF_ITERATOR in [])
    $.hide(O, FF_ITERATOR, value);
}
module.exports = {
  BUGGY: 'keys' in [] && !('next' in [].keys()),
  Iterators: Iterators,
  step: function(done, value) {
    return {
      value: value,
      done: !!done
    };
  },
  is: function(it) {
    var O = Object(it),
        Symbol = $.g.Symbol;
    return (Symbol && Symbol.iterator || FF_ITERATOR) in O || SYMBOL_ITERATOR in O || $.has(Iterators, classof(O));
  },
  get: function(it) {
    var Symbol = $.g.Symbol,
        getIter;
    if (it != undefined) {
      getIter = it[Symbol && Symbol.iterator || FF_ITERATOR] || it[SYMBOL_ITERATOR] || Iterators[classof(it)];
    }
    assert($.isFunction(getIter), it, ' is not iterable!');
    return assertObject(getIter.call(it));
  },
  set: setIterator,
  create: function(Constructor, NAME, next, proto) {
    Constructor.prototype = $.create(proto || IteratorPrototype, {next: $.desc(1, next)});
    cof.set(Constructor, NAME + ' Iterator');
  }
};
