<!--
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-->
<import src="observe.sky" as="observe" />

<script>
Node.prototype.bind = function(name, observable, oneTime) {
  var self = this;

  if (oneTime) {
    this[name] = observable;
    return;
  }

  observable.open(function(value) {
    self[name] = value;
  });

  return observable;
};

function sanitizeValue(value) {
  return value == null ? '' : value;
}

function updateText(node, value) {
  node.data = sanitizeValue(value);
}

function textBinding(node) {
  return function(value) {
    return updateText(node, value);
  };
}

Text.prototype.bind = function(name, value, oneTime) {
  if (name !== 'textContent')
    return Node.prototype.bind.call(this, name, value, oneTime);

  if (oneTime)
    return updateText(this, value);

  var observable = value;
  updateText(this, observable.open(textBinding(this)));
  return observable;
}

function updateAttribute(el, name, value) {
  el.setAttribute(name, sanitizeValue(value));
}

function attributeBinding(el, name) {
  return function(value) {
    updateAttribute(el, name, value);
  };
}

function bindAsAttribute(el, name) {
  if (name == 'style' || name == 'class')
    return true;
  if (el.tagName == 'a' && name == 'href')
    return true;
}

Element.prototype.bind = function(name, value, oneTime) {
  if (!bindAsAttribute(this, name))
    return Node.prototype.bind.call(this, name, value, oneTime);

  if (oneTime)
    return updateAttribute(this, name, value);

  var observable = value;
  updateAttribute(this, name, observable.open(attributeBinding(this, name)));
  return observable;
}

function getFragmentRoot(node) {
  var p;
  while (p = node.parentNode) {
    node = p;
  }

  return node;
}

function searchRefId(node, id) {
  if (!id)
    return;

  var ref;
  var selector = '#' + id;
  while (!ref) {
    node = getFragmentRoot(node);

    if (node.protoContent_)
      ref = node.protoContent_.querySelector(selector);
    else if (node.getElementById)
      ref = node.getElementById(id);

    if (ref || !node.templateCreator_)
      break

    node = node.templateCreator_;
  }

  return ref;
}

function getInstanceRoot(node) {
  while (node.parentNode) {
    node = node.parentNode;
  }
  return node.templateCreator_ ? node : null;
}

var BIND = 'bind';
var REPEAT = 'repeat';
var IF = 'if';

var templateAttributeDirectives = {
  'template': true,
  'repeat': true,
  'bind': true,
  'ref': true
};

function isTemplate(el) {
  if (el.isTemplate_ === undefined)
    el.isTemplate_ = el.tagName == 'template';

  return el.isTemplate_;
}

function mixin(to, from) {
  Object.getOwnPropertyNames(from).forEach(function(name) {
    Object.defineProperty(to, name,
                          Object.getOwnPropertyDescriptor(from, name));
  });
}

function getTemplateStagingDocument(template) {
  if (!template.stagingDocument_) {
    var owner = template.ownerDocument;
    if (!owner.stagingDocument_) {
      // FIXME(sky): Does this need to create a Document without a registration
      // context?
      owner.stagingDocument_ = new Document();
      owner.stagingDocument_.isStagingDocument = true;
      owner.stagingDocument_.stagingDocument_ = owner.stagingDocument_;
    }

    template.stagingDocument_ = owner.stagingDocument_;
  }

  return template.stagingDocument_;
}

var templateObserver;
if (typeof MutationObserver == 'function') {
  templateObserver = new MutationObserver(function(records) {
    for (var i = 0; i < records.length; i++) {
      records[i].target.refChanged_();
    }
  });
}

var contentDescriptor = {
  get: function() {
    return this.content_;
  },
  enumerable: true,
  configurable: true
};

function ensureSetModelScheduled(template) {
  if (!template.setModelFn_) {
    template.setModelFn_ = function() {
      template.setModelFnScheduled_ = false;
      var map = getBindings(template,
          template.delegate_ && template.delegate_.prepareBinding);
      processBindings(template, map, template.model_);
    };
  }

  if (!template.setModelFnScheduled_) {
    template.setModelFnScheduled_ = true;
    Observer.runEOM_(template.setModelFn_);
  }
}

mixin(HTMLTemplateElement.prototype, {
  bind: function(name, value, oneTime) {
    if (name != 'ref')
      return Element.prototype.bind.call(this, name, value, oneTime);

    var self = this;
    var ref = oneTime ? value : value.open(function(ref) {
      self.setAttribute('ref', ref);
      self.refChanged_();
    });

    this.setAttribute('ref', ref);
    this.refChanged_();
    if (oneTime)
      return;

    if (!this.bindings_) {
      this.bindings_ = { ref: value };
    } else {
      this.bindings_.ref = value;
    }

    return value;
  },

  processBindingDirectives_: function(directives) {
    if (this.iterator_)
      this.iterator_.closeDeps();

    if (!directives.if && !directives.bind && !directives.repeat) {
      if (this.iterator_) {
        this.iterator_.close();
        this.iterator_ = undefined;
      }

      return;
    }

    if (!this.iterator_) {
      this.iterator_ = new TemplateIterator(this);
    }

    this.iterator_.updateDependencies(directives, this.model_);

    if (templateObserver) {
      templateObserver.observe(this, { attributes: true,
                                       attributeFilter: ['ref'] });
    }

    return this.iterator_;
  },

  createInstance: function(model, bindingDelegate, delegate_) {
    if (bindingDelegate)
      delegate_ = this.newDelegate_(bindingDelegate);
    else if (!delegate_)
      delegate_ = this.delegate_;

    if (!this.refContent_)
      this.refContent_ = this.ref_.content;
    var content = this.refContent_;
    if (content.firstChild === null)
      return emptyInstance;

    var map = getInstanceBindingMap(content, delegate_);
    var stagingDocument = getTemplateStagingDocument(this);
    var instance = stagingDocument.createDocumentFragment();
    instance.templateCreator_ = this;
    instance.protoContent_ = content;
    instance.bindings_ = [];
    instance.terminator_ = null;
    var instanceRecord = instance.templateInstance_ = {
      firstNode: null,
      lastNode: null,
      model: model
    };

    var i = 0;
    var collectTerminator = false;
    for (var child = content.firstChild; child; child = child.nextSibling) {
      // The terminator of the instance is the clone of the last child of the
      // content. If the last child is an active template, it may produce
      // instances as a result of production, so simply collecting the last
      // child of the instance after it has finished producing may be wrong.
      if (child.nextSibling === null)
        collectTerminator = true;

      var clone = cloneAndBindInstance(child, instance, stagingDocument,
                                       map.children[i++],
                                       model,
                                       delegate_,
                                       instance.bindings_);
      clone.templateInstance_ = instanceRecord;
      if (collectTerminator)
        instance.terminator_ = clone;
    }

    instanceRecord.firstNode = instance.firstChild;
    instanceRecord.lastNode = instance.lastChild;
    instance.templateCreator_ = undefined;
    instance.protoContent_ = undefined;
    return instance;
  },

  get model() {
    return this.model_;
  },

  set model(model) {
    this.model_ = model;
    ensureSetModelScheduled(this);
  },

  get bindingDelegate() {
    return this.delegate_ && this.delegate_.raw;
  },

  refChanged_: function() {
    if (!this.iterator_ || this.refContent_ === this.ref_.content)
      return;

    this.refContent_ = undefined;
    this.iterator_.valueChanged();
    this.iterator_.updateIteratedValue(this.iterator_.getUpdatedValue());
  },

  clear: function() {
    this.model_ = undefined;
    this.delegate_ = undefined;
    if (this.bindings_ && this.bindings_.ref)
      this.bindings_.ref.close()
    this.refContent_ = undefined;
    if (!this.iterator_)
      return;
    this.iterator_.valueChanged();
    this.iterator_.close()
    this.iterator_ = undefined;
  },

  setDelegate_: function(delegate) {
    this.delegate_ = delegate;
    this.bindingMap_ = undefined;
    if (this.iterator_) {
      this.iterator_.instancePositionChangedFn_ = undefined;
      this.iterator_.instanceModelFn_ = undefined;
    }
  },

  newDelegate_: function(bindingDelegate) {
    if (!bindingDelegate)
      return;

    function delegateFn(name) {
      var fn = bindingDelegate && bindingDelegate[name];
      if (typeof fn != 'function')
        return;

      return function() {
        return fn.apply(bindingDelegate, arguments);
      };
    }

    return {
      bindingMaps: {},
      raw: bindingDelegate,
      prepareBinding: delegateFn('prepareBinding'),
      prepareInstanceModel: delegateFn('prepareInstanceModel'),
      prepareInstancePositionChanged:
          delegateFn('prepareInstancePositionChanged')
    };
  },

  set bindingDelegate(bindingDelegate) {
    if (this.delegate_) {
      throw Error('Template must be cleared before a new bindingDelegate ' +
                  'can be assigned');
    }

    this.setDelegate_(this.newDelegate_(bindingDelegate));
  },

  get ref_() {
    var ref = searchRefId(this, this.getAttribute('ref'));
    if (!ref)
      ref = this.instanceRef_;

    if (!ref)
      return this;

    var nextRef = ref.ref_;
    return nextRef ? nextRef : ref;
  }
});

// Returns
//   a) undefined if there are no mustaches.
//   b) [TEXT, (ONE_TIME?, PATH, DELEGATE_FN, TEXT)+] if there is at least
//      one mustache.
function parseMustaches(s, name, node, prepareBindingFn) {
  if (!s || !s.length)
    return;

  var tokens;
  var length = s.length;
  var startIndex = 0, lastIndex = 0, endIndex = 0;
  var onlyOneTime = true;
  while (lastIndex < length) {
    var startIndex = s.indexOf('{{', lastIndex);
    var oneTimeStart = s.indexOf('[[', lastIndex);
    var oneTime = false;
    var terminator = '}}';

    if (oneTimeStart >= 0 &&
        (startIndex < 0 || oneTimeStart < startIndex)) {
      startIndex = oneTimeStart;
      oneTime = true;
      terminator = ']]';
    }

    endIndex = startIndex < 0 ? -1 : s.indexOf(terminator, startIndex + 2);

    if (endIndex < 0) {
      if (!tokens)
        return;

      tokens.push(s.slice(lastIndex)); // TEXT
      break;
    }

    tokens = tokens || [];
    tokens.push(s.slice(lastIndex, startIndex)); // TEXT
    var pathString = s.slice(startIndex + 2, endIndex).trim();
    tokens.push(oneTime); // ONE_TIME?
    onlyOneTime = onlyOneTime && oneTime;
    var delegateFn = prepareBindingFn &&
                     prepareBindingFn(pathString, name, node);
    // Don't try to parse the expression if there's a prepareBinding function
    if (delegateFn == null) {
      tokens.push(observe.Path.get(pathString)); // PATH
    } else {
      tokens.push(null);
    }
    tokens.push(delegateFn); // DELEGATE_FN
    lastIndex = endIndex + 2;
  }

  if (lastIndex === length)
    tokens.push(''); // TEXT

  tokens.hasOnePath = tokens.length === 5;
  tokens.isSimplePath = tokens.hasOnePath &&
                        tokens[0] == '' &&
                        tokens[4] == '';
  tokens.onlyOneTime = onlyOneTime;

  tokens.combinator = function(values) {
    var newValue = tokens[0];

    for (var i = 1; i < tokens.length; i += 4) {
      var value = tokens.hasOnePath ? values : values[(i - 1) / 4];
      if (value !== undefined)
        newValue += value;
      newValue += tokens[i + 3];
    }

    return newValue;
  }

  return tokens;
};

function processOneTimeBinding(name, tokens, node, model) {
  if (tokens.hasOnePath) {
    var delegateFn = tokens[3];
    var value = delegateFn ? delegateFn(model, node, true) :
                             tokens[2].getValueFrom(model);
    return tokens.isSimplePath ? value : tokens.combinator(value);
  }

  var values = [];
  for (var i = 1; i < tokens.length; i += 4) {
    var delegateFn = tokens[i + 2];
    values[(i - 1) / 4] = delegateFn ? delegateFn(model, node) :
        tokens[i + 1].getValueFrom(model);
  }

  return tokens.combinator(values);
}

function processSinglePathBinding(name, tokens, node, model) {
  var delegateFn = tokens[3];
  var observer = delegateFn ? delegateFn(model, node, false) :
      new observe.PathObserver(model, tokens[2]);

  return tokens.isSimplePath ? observer :
      new observe.ObserverTransform(observer, tokens.combinator);
}

function processBinding(name, tokens, node, model) {
  if (tokens.onlyOneTime)
    return processOneTimeBinding(name, tokens, node, model);

  if (tokens.hasOnePath)
    return processSinglePathBinding(name, tokens, node, model);

  var observer = new observe.CompoundObserver();

  for (var i = 1; i < tokens.length; i += 4) {
    var oneTime = tokens[i];
    var delegateFn = tokens[i + 2];

    if (delegateFn) {
      var value = delegateFn(model, node, oneTime);
      if (oneTime)
        observer.addPath(value)
      else
        observer.addObserver(value);
      continue;
    }

    var path = tokens[i + 1];
    if (oneTime)
      observer.addPath(path.getValueFrom(model))
    else
      observer.addPath(model, path);
  }

  return new observe.ObserverTransform(observer, tokens.combinator);
}

function processBindings(node, bindings, model, instanceBindings) {
  for (var i = 0; i < bindings.length; i += 2) {
    var name = bindings[i]
    var tokens = bindings[i + 1];
    var value = processBinding(name, tokens, node, model);
    var binding = node.bind(name, value, tokens.onlyOneTime);
    if (binding && instanceBindings)
      instanceBindings.push(binding);
  }

  if (!bindings.isTemplate)
    return;

  node.model_ = model;
  var iter = node.processBindingDirectives_(bindings);
  if (instanceBindings && iter)
    instanceBindings.push(iter);
}

function parseWithDefault(el, name, prepareBindingFn) {
  var v = el.getAttribute(name);
  return parseMustaches(v == '' ? '{{}}' : v, name, el, prepareBindingFn);
}

function parseAttributeBindings(element, prepareBindingFn) {
  var bindings = [];
  var ifFound = false;
  var bindFound = false;
  var attributes = element.getAttributes();

  for (var i = 0; i < attributes.length; i++) {
    var attr = attributes[i];
    var name = attr.name;
    var value = attr.value;

    if (isTemplate(element) &&
        (name === IF || name === BIND || name === REPEAT)) {
      continue;
    }

    var tokens = parseMustaches(value, name, element,
                                prepareBindingFn);
    if (!tokens)
      continue;

    bindings.push(name, tokens);
  }

  if (isTemplate(element)) {
    bindings.isTemplate = true;
    bindings.if = parseWithDefault(element, IF, prepareBindingFn);
    bindings.bind = parseWithDefault(element, BIND, prepareBindingFn);
    bindings.repeat = parseWithDefault(element, REPEAT, prepareBindingFn);

    if (bindings.if && !bindings.bind && !bindings.repeat)
      bindings.bind = parseMustaches('{{}}', BIND, element, prepareBindingFn);
  }

  return bindings;
}

function getBindings(node, prepareBindingFn) {
  if (node instanceof Element) {
    return parseAttributeBindings(node, prepareBindingFn);
  }

  if (node instanceof Text) {
    var tokens = parseMustaches(node.data, 'textContent', node,
                                prepareBindingFn);
    if (tokens)
      return ['textContent', tokens];
  }

  return [];
}

function cloneAndBindInstance(node, parent, stagingDocument, bindings, model,
                              delegate,
                              instanceBindings,
                              instanceRecord) {
  var clone = parent.appendChild(stagingDocument.importNode(node, false));

  var i = 0;
  for (var child = node.firstChild; child; child = child.nextSibling) {
    cloneAndBindInstance(child, clone, stagingDocument,
                          bindings.children[i++],
                          model,
                          delegate,
                          instanceBindings);
  }

  if (bindings.isTemplate) {
    clone.instanceRef_ = node;

    if (delegate)
      clone.setDelegate_(delegate);
  }

  processBindings(clone, bindings, model, instanceBindings);
  return clone;
}

function createInstanceBindingMap(node, prepareBindingFn) {
  var map = getBindings(node, prepareBindingFn);
  map.children = {};
  var index = 0;
  for (var child = node.firstChild; child; child = child.nextSibling) {
    map.children[index++] = createInstanceBindingMap(child, prepareBindingFn);
  }

  return map;
}

var contentUidCounter = 1;

// TODO(rafaelw): Setup a MutationObserver on content which clears the id
// so that bindingMaps regenerate when the template.content changes.
function getContentUid(content) {
  var id = content.id_;
  if (!id)
    id = content.id_ = contentUidCounter++;
  return id;
}

// Each delegate is associated with a set of bindingMaps, one for each
// content which may be used by a template. The intent is that each binding
// delegate gets the opportunity to prepare the instance (via the prepare*
// delegate calls) once across all uses.
// TODO(rafaelw): Separate out the parse map from the binding map. In the
// current implementation, if two delegates need a binding map for the same
// content, the second will have to reparse.
function getInstanceBindingMap(content, delegate_) {
  var contentId = getContentUid(content);
  if (delegate_) {
    var map = delegate_.bindingMaps[contentId];
    if (!map) {
      map = delegate_.bindingMaps[contentId] =
          createInstanceBindingMap(content, delegate_.prepareBinding) || [];
    }
    return map;
  }

  var map = content.bindingMap_;
  if (!map) {
    map = content.bindingMap_ =
        createInstanceBindingMap(content, undefined) || [];
  }
  return map;
}

Object.defineProperty(Node.prototype, 'templateInstance', {
  get: function() {
    var instance = this.templateInstance_;
    return instance ? instance :
        (this.parentNode ? this.parentNode.templateInstance : undefined);
  }
});

var emptyInstance = document.createDocumentFragment();
emptyInstance.bindings_ = [];
emptyInstance.terminator_ = null;

function TemplateIterator(templateElement) {
  this.closed = false;
  this.templateElement_ = templateElement;
  this.instances = [];
  this.deps = undefined;
  this.iteratedValue = [];
  this.presentValue = undefined;
  this.arrayObserver = undefined;
}

TemplateIterator.prototype = {
  closeDeps: function() {
    var deps = this.deps;
    if (deps) {
      if (deps.ifOneTime === false)
        deps.ifValue.close();
      if (deps.oneTime === false)
        deps.value.close();
    }
  },

  updateDependencies: function(directives, model) {
    this.closeDeps();

    var deps = this.deps = {};
    var template = this.templateElement_;

    var ifValue = true;
    if (directives.if) {
      deps.hasIf = true;
      deps.ifOneTime = directives.if.onlyOneTime;
      deps.ifValue = processBinding(IF, directives.if, template, model);

      ifValue = deps.ifValue;

      // oneTime if & predicate is false. nothing else to do.
      if (deps.ifOneTime && !ifValue) {
        this.valueChanged();
        return;
      }

      if (!deps.ifOneTime)
        ifValue = ifValue.open(this.updateIfValue, this);
    }

    if (directives.repeat) {
      deps.repeat = true;
      deps.oneTime = directives.repeat.onlyOneTime;
      deps.value = processBinding(REPEAT, directives.repeat, template, model);
    } else {
      deps.repeat = false;
      deps.oneTime = directives.bind.onlyOneTime;
      deps.value = processBinding(BIND, directives.bind, template, model);
    }

    var value = deps.value;
    if (!deps.oneTime)
      value = value.open(this.updateIteratedValue, this);

    if (!ifValue) {
      this.valueChanged();
      return;
    }

    this.updateValue(value);
  },

  /**
   * Gets the updated value of the bind/repeat. This can potentially call
   * user code (if a bindingDelegate is set up) so we try to avoid it if we
   * already have the value in hand (from Observer.open).
   */
  getUpdatedValue: function() {
    var value = this.deps.value;
    if (!this.deps.oneTime)
      value = value.discardChanges();
    return value;
  },

  updateIfValue: function(ifValue) {
    if (!ifValue) {
      this.valueChanged();
      return;
    }

    this.updateValue(this.getUpdatedValue());
  },

  updateIteratedValue: function(value) {
    if (this.deps.hasIf) {
      var ifValue = this.deps.ifValue;
      if (!this.deps.ifOneTime)
        ifValue = ifValue.discardChanges();
      if (!ifValue) {
        this.valueChanged();
        return;
      }
    }

    this.updateValue(value);
  },

  updateValue: function(value) {
    if (!this.deps.repeat)
      value = [value];
    var observe = this.deps.repeat &&
                  !this.deps.oneTime &&
                  Array.isArray(value);
    this.valueChanged(value, observe);
  },

  valueChanged: function(value, observeValue) {
    if (!Array.isArray(value))
      value = [];

    if (value === this.iteratedValue)
      return;

    this.unobserve();
    this.presentValue = value;
    if (observeValue) {
      this.arrayObserver = new observe.ArrayObserver(this.presentValue);
      this.arrayObserver.open(this.handleSplices, this);
    }

    this.handleSplices(observe.ArrayObserver.calculateSplices(this.presentValue,
                                                      this.iteratedValue));
  },

  getLastInstanceNode: function(index) {
    if (index == -1)
      return this.templateElement_;
    var instance = this.instances[index];
    var terminator = instance.terminator_;
    if (!terminator)
      return this.getLastInstanceNode(index - 1);

    if (terminator.nodeType !== Node.ELEMENT_NODE ||
        this.templateElement_ === terminator) {
      return terminator;
    }

    var subtemplateIterator = terminator.iterator_;
    if (!subtemplateIterator)
      return terminator;

    return subtemplateIterator.getLastTemplateNode();
  },

  getLastTemplateNode: function() {
    return this.getLastInstanceNode(this.instances.length - 1);
  },

  insertInstanceAt: function(index, fragment) {
    var previousInstanceLast = this.getLastInstanceNode(index - 1);
    var parent = this.templateElement_.parentNode;
    this.instances.splice(index, 0, fragment);

    parent.insertBefore(fragment, previousInstanceLast.nextSibling);
  },

  extractInstanceAt: function(index) {
    var previousInstanceLast = this.getLastInstanceNode(index - 1);
    var lastNode = this.getLastInstanceNode(index);
    var parent = this.templateElement_.parentNode;
    var instance = this.instances.splice(index, 1)[0];

    while (lastNode !== previousInstanceLast) {
      var node = previousInstanceLast.nextSibling;
      if (node == lastNode)
        lastNode = previousInstanceLast;

      instance.appendChild(parent.removeChild(node));
    }

    return instance;
  },

  getDelegateFn: function(fn) {
    fn = fn && fn(this.templateElement_);
    return typeof fn === 'function' ? fn : null;
  },

  handleSplices: function(splices) {
    if (this.closed || !splices.length)
      return;

    var template = this.templateElement_;

    if (!template.parentNode) {
      this.close();
      return;
    }

    observe.ArrayObserver.applySplices(this.iteratedValue, this.presentValue,
                               splices);

    var delegate = template.delegate_;
    if (this.instanceModelFn_ === undefined) {
      this.instanceModelFn_ =
          this.getDelegateFn(delegate && delegate.prepareInstanceModel);
    }

    if (this.instancePositionChangedFn_ === undefined) {
      this.instancePositionChangedFn_ =
          this.getDelegateFn(delegate &&
                             delegate.prepareInstancePositionChanged);
    }

    // Instance Removals
    var instanceCache = new Map;
    var removeDelta = 0;
    for (var i = 0; i < splices.length; i++) {
      var splice = splices[i];
      var removed = splice.removed;
      for (var j = 0; j < removed.length; j++) {
        var model = removed[j];
        var instance = this.extractInstanceAt(splice.index + removeDelta);
        if (instance !== emptyInstance) {
          instanceCache.set(model, instance);
        }
      }

      removeDelta -= splice.addedCount;
    }

    // Instance Insertions
    for (var i = 0; i < splices.length; i++) {
      var splice = splices[i];
      var addIndex = splice.index;
      for (; addIndex < splice.index + splice.addedCount; addIndex++) {
        var model = this.iteratedValue[addIndex];
        var instance = instanceCache.get(model);
        if (instance) {
          instanceCache.delete(model);
        } else {
          if (this.instanceModelFn_) {
            model = this.instanceModelFn_(model);
          }

          if (model === undefined) {
            instance = emptyInstance;
          } else {
            instance = template.createInstance(model, undefined, delegate);
          }
        }

        this.insertInstanceAt(addIndex, instance);
      }
    }

    instanceCache.forEach(function(instance) {
      this.closeInstanceBindings(instance);
    }, this);

    if (this.instancePositionChangedFn_)
      this.reportInstancesMoved(splices);
  },

  reportInstanceMoved: function(index) {
    var instance = this.instances[index];
    if (instance === emptyInstance)
      return;

    this.instancePositionChangedFn_(instance.templateInstance_, index);
  },

  reportInstancesMoved: function(splices) {
    var index = 0;
    var offset = 0;
    for (var i = 0; i < splices.length; i++) {
      var splice = splices[i];
      if (offset != 0) {
        while (index < splice.index) {
          this.reportInstanceMoved(index);
          index++;
        }
      } else {
        index = splice.index;
      }

      while (index < splice.index + splice.addedCount) {
        this.reportInstanceMoved(index);
        index++;
      }

      offset += splice.addedCount - splice.removed.length;
    }

    if (offset == 0)
      return;

    var length = this.instances.length;
    while (index < length) {
      this.reportInstanceMoved(index);
      index++;
    }
  },

  closeInstanceBindings: function(instance) {
    var bindings = instance.bindings_;
    for (var i = 0; i < bindings.length; i++) {
      bindings[i].close();
    }
  },

  unobserve: function() {
    if (!this.arrayObserver)
      return;

    this.arrayObserver.close();
    this.arrayObserver = undefined;
  },

  close: function() {
    if (this.closed)
      return;
    this.unobserve();
    for (var i = 0; i < this.instances.length; i++) {
      this.closeInstanceBindings(this.instances[i]);
    }

    this.instances.length = 0;
    this.closeDeps();
    this.templateElement_.iterator_ = undefined;
    this.closed = true;
  }
};
</script>
