import 'dart:async';

void assertHasParentNode(Node n) { assert(n.parentNode != null); }
void assertHasParentNodes(List<Node> list) {
  for (var n in list) {
    assertHasParentNode(n);
  }
}

class Node {

  ParentNode parentNode;
  Node nextSibling;
  Node previousSibling;
  Node();

  void insertBefore(List<Node> nodes) {
    int count = nodes.length;
    while (count-- > 0) {
      parentNode._insertBefore(nodes[count], this);
    }

    assertHasParentNodes(nodes);
  }

  remove() {
    if (parentNode == null) {
      return;
    }

    if (nextSibling != null) {
      nextSibling.previousSibling = previousSibling;
    } else {
      parentNode.lastChild = previousSibling;
    }

    if (previousSibling != null) {
      previousSibling.nextSibling = nextSibling;
    } else {
      parentNode.firstChild = nextSibling;
    }

    parentNode = null;
    nextSibling = null;
    previousSibling = null;
  }
}

class Text extends Node {
  String data;
  Text(this.data) : super();
}

class ParentNode extends Node {
  Node firstChild;
  Node lastChild;

  ParentNode() : super();

  Node setChild(Node node) {
    firstChild = node;
    lastChild = node;
    node.parentNode = this;
    assertHasParentNode(node);
    return node;
  }

  Node _insertBefore(Node node, Node ref) {
    assert(ref == null || ref.parentNode == this);

    if (node.parentNode != null) {
      node.remove();
    }

    node.parentNode = this;

    if (firstChild == null && lastChild == null) {
      firstChild = node;
      lastChild = node;
    } else if (ref == null) {
      node.previousSibling = lastChild;
      lastChild.nextSibling = node;
      lastChild = node;
    } else {
      if (ref == firstChild) {
        assert(ref.previousSibling == null);
        firstChild = node;
      }
      node.previousSibling = ref.previousSibling;
      ref.previousSibling = node;
      node.nextSibling = ref;
    }

    assertHasParentNode(node);
    return node;
  }

  Node appendChild(Node node) {
    return _insertBefore(node, null);
  }
}

class Element extends ParentNode {
  void addEventListener(String type, EventListener listener, [bool useCapture = false]) {}
  void removeEventListener(String type, EventListener listener) {}
  void setAttribute(String name, [String value]) {}
}

class Document extends ParentNode {
  Document();
  Element createElement(String tagName) {
    switch (tagName) {
      case 'img' : return new HTMLImageElement();
      default : return new Element();
    }
  }
}

class HTMLImageElement extends Element {
  HTMLImageElement();
  String src;
  Object style = {};
}

class Event {}

class PointerEvent extends Event {}
class GestureEvent extends Event {}
class WheelEvent extends Event {}

typedef EventListener(Event event);

void _callRAF(Function fn) {
  fn(new DateTime.now().millisecondsSinceEpoch.toDouble());
}

class Window {
  int requestAnimationFrame(Function fn) {
    new Timer(const Duration(milliseconds: 16), () {
      _callRAF(fn);
    });
    return 1;
  }

  void cancelAnimationFrame(int id) {
  }
}

Document document = new Document();

Window window = new Window();

class ClientRect {
    double top;
    double right;
    double bottomr;
    double left;
    double width;
    double height;
}
