<!--
// 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="sky-binder.sky" as="binder" />
<script>
// TODO(esprehn): It would be nice if these were exposed by the platform so
// the framework didn't need to hard code a list.
var globalAttributesNames = new Set([
  'class',
  'contenteditable',
  'dir',
  'id',
  'lang',
  'spellcheck',
  'tabindex',
  'style',
]);

function isExpandableAttribute(name) {
  return name.startsWith('data-') || name.startsWith('on-');
}

function isGlobalAttribute(name) {
  if (isExpandableAttribute(name))
    return true;
  return globalAttributesNames.has(name);
}

var attributeConverters = {
  boolean: function(value) {
    if (typeof value == 'string')
      return value == 'true';
    return !!value;
  },
  number: function(value) {
    return Number(value);
  },
  string: function(value) {
    if (value === null)
      return '';
    return String(value);
  },
};

function eventHandlerCallback(event) {
  var element = event.currentTarget;
  var registration = getRegistration(element.localName);
  var method = registration.eventHandlers.get(event.type);
  var handler = element[method];
  if (!(typeof handler == 'function')) {
    throw new Error('Element ' + element.localName +
        ' specifies invalid event handler "' + method + '"');
  }
  handler.call(element, event);
}

class ElementRegistration {
  constructor(tagName) {
    this.tagName = tagName;
    this.attributes = new Map();
    this.eventHandlers = new Map();
    this.template = null;
    Object.preventExtensions(this);
  }

  allowsAttribute(name) {
    if (isGlobalAttribute(name))
      return true;
    if (this.attributes.has(name))
      return true;
    return false;
  }

  defineAttribute(name, type) {
    var converter = attributeConverters[type];

    if (!converter) {
      console.error('Invalid attribute type "' + type + '", type must be one'
          + ' of boolean, number or string.');
      return;
    }

    this.attributes.set(name, converter);
  }

  synthesizeAttributes(prototype) {
    this.attributes.forEach(function(converter, name) {
      Object.defineProperty(prototype, name, {
        get: function() {
          return converter(this.getAttribute(name));
        },
        set: function(newValue) {
          this.setAttribute(name, converter(newValue));
        },
        enumerable: true,
        configurable: true,
      });
    });
  }

  addInstanceEventListeners(instance) {
    for (var eventName of this.eventHandlers.keys()) {
      instance.addEventListener(eventName, eventHandlerCallback);
    }
  }
}

var registrations = new Map();

function registerElement(tagName, attributes) {
  if (registrations.has(tagName))
    throw new Error('tagName "' + tagName + '" registered twice.');
  var registration = new ElementRegistration(tagName);
  for (var name in attributes) {
    registration.defineAttribute(name, attributes[name]);
  }
  registrations.set(tagName, registration);
  return registration;
}

function getRegistration(tagName) {
  return registrations.get(tagName);
}

function checkAttribute(tagName, attrName) {
  var registration = getRegistration(tagName);

  if (!registration)
    return isGlobalAttribute(attrName);

  return registration.allowsAttribute(attrName);
}

registerElement('img', {
  'width': 'number',
  'height': 'number',
  // TODO(esprehn): Sky probably doesn't want the crossorign attr.
  'crossorigin': 'string',
  'src': 'string',
});

registerElement('import', {
  'as': 'string',
  'src': 'string',
  'async': 'boolean',
});

registerElement('a', {
  'href': 'string',
  'async': 'boolean',
});

registerElement('content', {
  'select': 'string',
});

registerElement('style', {
  'media': 'string',
});

registerElement('template', {
  'if': 'string',
  'repeat': 'string',
});

registerElement('iframe', {
  'src': 'string',
});

module.exports = {
  registerElement: registerElement,
  getRegistration: getRegistration,
  checkAttribute: checkAttribute,
  isGlobalAttribute: isGlobalAttribute,
  isExpandableAttribute: isExpandableAttribute,
};
</script>
