<!--
// 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;
  }

  this[name] = 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 addEventHandler(element, name, method) {
  element.addEventListener(name, function(event) {
    var scope = element.ownerScope;
    var host = scope.host;
    var handler = host && host[method];
    if (handler instanceof Function)
      return handler.call(host, event);
  });
}

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;
    }

    if (name.startsWith('on-')) {
      if (!bindings.eventHandlers)
        bindings.eventHandlers = new Map();
      bindings.eventHandlers.set(name.substring(3), value);
      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);
  }

  if (bindings.eventHandlers) {
    bindings.eventHandlers.forEach(function(handler, eventName) {
      addEventHandler(clone, eventName, handler);
    });
  }

  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>
