<!--
// Copyright 2015 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.
-->
<script>
import "dart:mirrors";
import "dart:sky";

typedef dynamic _Converter(String value);

final Map<String, _Converter> _kAttributeConverters = {
  'boolean': (String value) {
    return value == 'true';
  },
  'number': (String value) {
    try {
      return double.parse(value);
    } catch(_) {
      return 0.0;
    }
  },
  'string': (String value) {
    return value == null ? '' : value;
  },
};

class _Registration {
  final Element template;
  final Map<String, _Converter> attributes = new Map();

  _Registration(this.template);

  void parseAttributeSpec(definition) {
    String spec = definition.getAttribute('attributes');
    if (spec == null)
      return;
  
    for (String token in spec.split(',')) {
      List<String> parts = token.split(':');

      if (parts.length != 2) {
        window.console.error(
            'Invalid attribute spec "${spec}", attributes must'
            ' be {name}:{type}, where type is one of boolean, number or'
            ' string.');
        continue;
      }
  
      var name = parts[0].trim();
      var type = parts[1].trim();
  
      defineAttribute(name, type);
    }
  }

  void defineAttribute(String name, String type) {
    _Converter converter = _kAttributeConverters[type];

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

    attributes[name] = converter;
  }
}

final Map<String, _Registration> _registery = new Map<String, _Registration>();

class Tagname {
  final String name;
  const Tagname(this.name);
}

String _getTagName(Type type) {
  return reflectClass(type).metadata.firstWhere(
      (i) => i.reflectee is Tagname).reflectee.name;
}

abstract class SkyElement extends Element {
  // Override these functions to receive lifecycle notifications.
  void created() {}
  void attached() {}
  void detached() {}
  void attributeChanged(String attrName, String oldValue, String newValue) {}
  void shadowRootReady() {}

  String get tagName => _getTagName(runtimeType);
  _Registration _registration;

  SkyElement() {
    _registration = _registery[tagName];
    // Invoke attributeChanged callback when element is first created too.
    // TODO(abarth): Is this necessary? We shouldn't have any attribute yet...
    for (Attr attribute in getAttributes())
      attributeChangedCallback(attribute.name, null, attribute.value);
  }

  attachedCallback() {
    if (shadowRoot == null) {
      if (_registration.template != null) {
        ShadowRoot shadow = ensureShadowRoot();
        Node content = _registration.template.content;
        shadow.appendChild(document.importNode(content, deep: true));
        shadowRootReady();
      }
    }
    attached();
  }

  detachedCallback() {
    detached();
  }

  attributeChangedCallback(name, oldValue, newValue) {
    attributeChanged(name, oldValue, newValue);

    _Converter converter = _registration.attributes[name];
    if (converter == null)
      return;
    Symbol callback = new Symbol('${name}Changed');
    InstanceMirror mirror = reflect(this);
    if (mirror.type.instanceMembers.containsKey(callback))
      mirror.invoke(callback, [converter(oldValue), converter(newValue)]);
  }

  noSuchMethod(Invocation invocation) {
    String name = MirrorSystem.getName(invocation.memberName);
    if (name.endsWith('='))
      name = name.substring(0, name.length - 1);
    _Converter converter = _registration.attributes[name];
    if (converter != null) {
      if (invocation.isGetter) {
        return converter(getAttribute(name));
      } else if (invocation.isSetter) {
        setAttribute(name, invocation.positionalArguments[0].toString());
        return;
      }
    }
    return super.noSuchMethod(invocation);
  }
}

void register(Element script, Type type) {
  Element definition = script.parentNode;

  if (definition.tagName != 'sky-element')
    throw new UnsupportedError('register() calls must be inside a <sky-element>.');

  ClassMirror mirror = reflectClass(type);
  if (!mirror.isSubclassOf(reflectClass(SkyElement)))
    throw new UnsupportedError('@Tagname can only be used on descendants of SkyElement');

  String tagName = _getTagName(type);
  Element template = definition.querySelector('template');

  document.registerElement(tagName, type);
  _registery[tagName] = new _Registration(template)
                        ..parseAttributeSpec(definition);
}
</script>
