<!--
// 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)
      continue;

    directives.properties.push(property);
  }
}

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;
    Object.preventExtensions(this);

    if (node instanceof Element) {
      parseAttributeDirectives(node, this);
    } 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.node, false);

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

    var clone = parent.appendChild(clone);

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

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

    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>
