<!--
// 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" />
<import src="element-registry.sky" as="registry" />

<script>
var stagingDocument = new Document();

class TemplateInstance {
  constructor() {
    this.bindings = [];
    this.terminator = null;
    this.fragment = stagingDocument.createDocumentFragment();
    Object.preventExtensions(this);
  }
  close() {
    var bindings = this.bindings;
    for (var i = 0; i < bindings.length; i++) {
      bindings[i].close();
    }
  }
}

var emptyInstance = new TemplateInstance();
var directiveCache = new WeakMap();

function createInstance(template, model) {
  var content = template.content;
  if (!content.firstChild)
    return emptyInstance;

  var directives = directiveCache.get(content);
  if (!directives) {
    directives = new NodeDirectives(content);
    directiveCache.set(content, directives);
  }

  var instance = new TemplateInstance();

  var length = directives.children.length;
  for (var i = 0; i < length; ++i) {
    var clone = directives.children[i].createBoundClone(instance.fragment,
        model, instance.bindings);

    // 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 (i == length - 1)
      instance.terminator = clone;
  }

  return instance;
}

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

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

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

class BindingExpression {
  constructor(prefix, path) {
    this.prefix = prefix;
    this.path = observe.Path.get(path);
    Object.preventExtensions(this);
  }
}

class PropertyDirective {
  constructor(name) {
    this.name = name;
    this.expressions = [];
    this.suffix = "";
    Object.preventExtensions(this);
  }
  createObserver(model) {
    var expressions = this.expressions;
    var suffix = this.suffix;

    if (expressions.length == 1 && expressions[0].prefix == "" && suffix == "")
      return new observe.PathObserver(model, expressions[0].path);

    var observer = new observe.CompoundObserver();

    for (var i = 0; i < expressions.length; ++i)
      observer.addPath(model, expressions[i].path);

    return new observe.ObserverTransform(observer, function(values) {
      var buffer = "";
      for (var i = 0; i < values.length; ++i) {
        buffer += expressions[i].prefix;
        buffer += values[i];
      }
      buffer += suffix;
      return buffer;
    });
  }
  bindProperty(node, model) {
    var name = this.name;
    var observable = this.createObserver(model);
    if (node instanceof Text) {
      updateText(node, observable.open(function(value) {
        return updateText(node, value);
      }));
    } else if (name == 'style' || name == 'class') {
      updateAttribute(node, name, observable.open(function(value) {
        updateAttribute(node, name, value);
      }));
    } else {
      node[name] = observable.open(function(value) {
        node[name] = value;
      });
    }
    if (typeof node.addPropertyBinding == 'function')
      node.addPropertyBinding(this.name, observable);
    return observable;
  }
}

function parsePropertyDirective(value, property) {
  if (!value || !value.length)
    return;

  var result;
  var offset = 0;
  var firstIndex = 0;
  var lastIndex = 0;

  while (offset < value.length) {
    firstIndex = value.indexOf('{{', offset);
    if (firstIndex == -1)
      break;
    lastIndex = value.indexOf('}}', firstIndex + 2);
    if (lastIndex == -1)
      lastIndex = value.length;
    var prefix = value.substring(offset, firstIndex);
    var path = value.substring(firstIndex + 2, lastIndex);
    offset = lastIndex + 2;
    if (!result)
      result = new PropertyDirective(property);
    result.expressions.push(new BindingExpression(prefix, path));
  }

  if (result && offset < value.length)
    result.suffix = value.substring(offset);

  return result;
}

function parseAttributeDirectives(element, directives) {
  var attributes = element.getAttributes();
  var tagName = element.tagName;

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

    if (name.startsWith('on-')) {
      directives.eventHandlers.push(name.substring(3));
      continue;
    }

    if (!registry.checkAttribute(tagName, name)) {
      console.error('Element "'+ tagName +
          '" has unknown attribute "' + name + '".');
    }

    var property = parsePropertyDirective(value, name);
    if (property)
      directives.properties.push(property);
  }
}

function createCloneSource(element, properties) {
  if (!properties.length)
    return element;

  // Leave attributes alone on template so you can see the if/repeat statements
  // in the inspector.
  if (element instanceof HTMLTemplateElement)
    return element;

  var result = element.cloneNode(false);

  for (var i = 0; i < properties.length; ++i) {
    result.removeAttribute(properties[i].name);
  }

  return result;
}

function eventHandlerCallback(event) {
  var element = event.currentTarget;
  var method = element.getAttribute('on-' + event.type);
  var scope = element.ownerScope;
  var host = scope.host;
  var handler = host && host[method];
  if (handler instanceof Function)
    return handler.call(host, event);
}

class NodeDirectives {
  constructor(node) {
    this.eventHandlers = [];
    this.children = [];
    this.properties = [];
    this.node = node;
    this.cloneSourceNode = node;
    Object.preventExtensions(this);

    if (node instanceof Element) {
      parseAttributeDirectives(node, this);
      this.cloneSourceNode = createCloneSource(node, this.properties);
    } else if (node instanceof Text) {
      var property = parsePropertyDirective(node.data, 'textContent');
      if (property)
        this.properties.push(property);
    }

    for (var child = node.firstChild; child; child = child.nextSibling) {
      this.children.push(new NodeDirectives(child));
    }
  }
  findProperty(name) {
    for (var i = 0; i < this.properties.length; ++i) {
      if (this.properties[i].name === name)
        return this.properties[i];
    }
    return null;
  }
  createBoundClone(parent, model, bindings) {
    // TODO(esprehn): In sky instead of needing to use a staging docuemnt per
    // custom element registry we're going to need to use the current module's
    // registry.
    var clone = stagingDocument.importNode(this.cloneSourceNode, false);

    for (var i = 0; i < this.eventHandlers.length; ++i) {
      clone.addEventListener(this.eventHandlers[i], eventHandlerCallback);
    }

    for (var i = 0; i < this.properties.length; ++i) {
      bindings.push(this.properties[i].bindProperty(clone, model));
    }

    parent.appendChild(clone);

    for (var i = 0; i < this.children.length; ++i) {
      this.children[i].createBoundClone(clone, model, bindings);
    }

    if (clone instanceof HTMLTemplateElement) {
      var iterator = new TemplateIterator(clone);
      iterator.updateDependencies(this, model);
      bindings.push(iterator);
    }

    return clone;
  }
}

var iterators = new WeakMap();

class TemplateIterator {
  constructor(element) {
    this.closed = false;
    this.template = element;
    this.contentTemplate = null;
    this.instances = [];
    this.hasRepeat = false;
    this.ifObserver = null;
    this.valueObserver = null;
    this.iteratedValue = [];
    this.presentValue = null;
    this.arrayObserver = null;
    Object.preventExtensions(this);
    iterators.set(element, this);
  }

  updateDependencies(directives, model) {
    this.contentTemplate = directives.node;

    var ifValue = true;
    var ifProperty = directives.findProperty('if');
    if (ifProperty) {
      this.ifObserver = ifProperty.createObserver(model);
      ifValue = this.ifObserver.open(this.updateIfValue, this);
    }

    var repeatProperty = directives.findProperty('repeat');
    if (repeatProperty) {
      this.hasRepeat = true;
      this.valueObserver = repeatProperty.createObserver(model);
    } else {
      var path = observe.Path.get("");
      this.valueObserver = new observe.PathObserver(model, path);
    }

    var value = this.valueObserver.open(this.updateIteratedValue, this);
    this.updateValue(ifValue ? value : null);
  }

  getUpdatedValue() {
    return this.valueObserver.discardChanges();
  }

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

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

  updateIteratedValue(value) {
    if (this.ifObserver) {
      var ifValue = this.ifObserver.discardChanges();
      if (!ifValue) {
        this.valueChanged();
        return;
      }
    }

    this.updateValue(value);
  }

  updateValue(value) {
    if (!this.hasRepeat)
      value = [value];
    var observe = this.hasRepeat && Array.isArray(value);
    this.valueChanged(value, observe);
  }

  valueChanged(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(index) {
    if (index == -1)
      return this.template;
    var instance = this.instances[index];
    var terminator = instance.terminator;
    if (!terminator)
      return this.getLastInstanceNode(index - 1);

    if (!(terminator instanceof Element) || this.template === terminator) {
      return terminator;
    }

    var subtemplateIterator = iterators.get(terminator);
    if (!subtemplateIterator)
      return terminator;

    return subtemplateIterator.getLastTemplateNode();
  }

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

  insertInstanceAt(index, instance) {
    var previousInstanceLast = this.getLastInstanceNode(index - 1);
    var parent = this.template.parentNode;
    this.instances.splice(index, 0, instance);
    parent.insertBefore(instance.fragment, previousInstanceLast.nextSibling);
  }

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

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

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

    return instance;
  }

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

    var template = this.template;

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

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

    // 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 (model === undefined || model === null) {
            instance = emptyInstance;
          } else {
            instance = createInstance(this.contentTemplate, model);
          }
        }

        this.insertInstanceAt(addIndex, instance);
      }
    }

    instanceCache.forEach(function(instance) {
      instance.close();
    });
  }

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

    this.arrayObserver.close();
    this.arrayObserver = null;
  }

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

    this.instances.length = 0;

    if (this.ifObserver)
      this.ifObserver.close();
    if (this.valueObserver)
      this.valueObserver.close();

    iterators.delete(this.template);
    this.closed = true;
  }
}

module.exports = {
  createInstance: createInstance,
};
</script>
