import { isFunction } from './typeof.js';
import { registry } from './registry.js';

const CONNECTED = 'connectedCallback';
const DISCONNECTED = 'disconnectedCallback';
const UPDATED = 'attributeChangedCallback';

export function getComponent(node) {
    if (node.nodeType === Node.ELEMENT_NODE) {
        let is = node.getAttribute('is') || node.tagName;
        return registry.get(is);
    }
    return null;
}

export function connect(node) {
    if (isFunction(node[CONNECTED])) {
        node[CONNECTED]();
    }
}

export function disconnect(node) {
    if (isFunction(node[DISCONNECTED])) {
        node[DISCONNECTED]();
    }
}

export function update(node, name, oldValue, newValue) {
    if (isFunction(node[UPDATED]) && name !== 'is') {
        node[UPDATED](name, oldValue, newValue);
    }
}

export function bind(node, Ctr) {
    node.__proto__ = Ctr.prototype;
    Object.defineProperty(node, 'constructor', {
        value: Ctr,
        configurable: true,
        writable: true,
    });
    Ctr.call(node);
}

export function create(node, descriptor) {
    descriptor = descriptor || getComponent(node);
    if (descriptor) {
        bind(node, descriptor.Ctr);
        connect(node);
    }
}

export function appendChild(parent, node) {
    if (parent !== node.parentNode || parent.lastElementChild !== node) {
        if (node.parentNode) {
            removeChild(node.parentNode, node);
        }
        parent.appendChild(node);
        connect(node);
    }
}

export function removeChild(parent, node) {
    parent.removeChild(node);
    disconnect(node);
}

@@ -403,12 +403,26 @@
 urn 
-null
+registry.get(node)
 ;%0A%7D%0A
@@ -508,33 +508,42 @@
  node%5BCONNECTED%5D
-(
+.call(node
 );%0A    %7D%0A%7D%0A%0Aexpo
@@ -641,17 +641,26 @@
 NNECTED%5D
-(
+.call(node
 );%0A    %7D
@@ -795,17 +795,28 @@
 UPDATED%5D
-(
+.call(node, 
 name, ol
@@ -1241,32 +1241,175 @@
 node);%0A    %7D%0A%7D%0A%0A
+export function createElement(is) %7B%0A    let descriptor = getComponent(is);%0A    if (descriptor) %7B%0A        return new descriptor.Ctr();%0A    %7D%0A%7D%0A%0A
 export function 
@@ -1735,24 +1735,24 @@
 hild(node);%0A
-
     disconne
@@ -1755,16 +1755,569 @@
 onnect(node);%0A%7D%0A
+%0Aexport function setAttribute(node, name, value) %7B%0A    let oldValue = node.getAttribute(name);%0A    node.setAttribute(name, value);%0A    let attrs = node.constructor.observedAttributes %7C%7C %5B%5D;%0A    if (attrs.indexOf(name) !== -1) %7B%0A        update(node, name, oldValue, value);%0A    %7D%0A%7D%0A%0Aexport function removeAttribute(node, name) %7B%0A    let oldValue = node.getAttribute(name);%0A    node.removeAttribute(name);%0A    let attrs = node.constructor.observedAttributes %7C%7C %5B%5D;%0A    if (attrs.indexOf(name) !== -1) %7B%0A        update(node, name, oldValue, null);%0A    %7D%0A%7D%0A

add attribute methods to nodes lib