library layout;

import 'node.dart';
import 'dart:sky' as sky;
import 'dart:collection';

// UTILS

// Bridge to legacy CSS-like style specification
// Eventually we'll replace this with something else
class Style {
  final String _className;
  static final Map<String, Style> _cache = new HashMap<String, Style>();

  static int _nextStyleId = 1;

  static String _getNextClassName() { return "style${_nextStyleId++}"; }

  Style extend(Style other) {
    var className = "$_className ${other._className}";

    return _cache.putIfAbsent(className, () {
      return new Style._internal(className);
    });
  }

  factory Style(String styles) {
    return _cache.putIfAbsent(styles, () {
      var className = _getNextClassName();
      sky.Element styleNode = sky.document.createElement('style');
      styleNode.setChild(new sky.Text(".$className { $styles }"));
      sky.document.appendChild(styleNode);
      return new Style._internal(className);
    });
  }

  Style._internal(this._className);
}

class Rect {
  const Rect(this.x, this.y, this.width, this.height);
  final double x;
  final double y;
  final double width;
  final double height;
}


// ABSTRACT LAYOUT

class ParentData {
  void detach() {
    detachSiblings();
  }
  void detachSiblings() { } // workaround for lack of inter-class mixins in Dart
}

abstract class RenderNode extends Node {

  // LAYOUT

  // parentData is only for use by the RenderNode that actually lays this
  // node out, and any other nodes who happen to know exactly what
  // kind of node that is.
  ParentData parentData;
  void setupPos(RenderNode child) {
    // override this to setup .parentData correctly for your class
    if (child.parentData is! ParentData)
      child.parentData = new ParentData();
  }

  void setAsChild(RenderNode child) { // only for use by subclasses
    // call this whenever you decide a node is a child
    assert(child != null);
    setupPos(child);
    super.setAsChild(child);
  }
  void dropChild(RenderNode child) { // only for use by subclasses
    assert(child != null);
    assert(child.parentData != null);
    child.parentData.detach();
    super.dropChild(child);
  }

}

abstract class RenderBox extends RenderNode { }


// GENERIC MIXIN FOR RENDER NODES THAT TAKE A LIST OF CHILDREN

abstract class ContainerParentDataMixin<ChildType extends RenderNode> {
  ChildType previousSibling;
  ChildType nextSibling;
  void detachSiblings() {
    if (previousSibling != null) {
      assert(previousSibling.parentData is ContainerParentDataMixin<ChildType>);
      assert(previousSibling != this);
      assert(previousSibling.parentData.nextSibling == this);
      previousSibling.parentData.nextSibling = nextSibling;
    }
    if (nextSibling != null) {
      assert(nextSibling.parentData is ContainerParentDataMixin<ChildType>);
      assert(nextSibling != this);
      assert(nextSibling.parentData.previousSibling == this);
      nextSibling.parentData.previousSibling = previousSibling;
    }
    previousSibling = null;
    nextSibling = null;
  }
}

abstract class ContainerRenderNodeMixin<ChildType extends RenderNode, ParentDataType extends ContainerParentDataMixin<ChildType>> implements RenderNode {
  // abstract class that has only InlineNode children

  bool _debugUltimatePreviousSiblingOf(ChildType child, { ChildType equals }) {
    assert(child.parentData is ParentDataType);
    while (child.parentData.previousSibling != null) {
      assert(child.parentData.previousSibling != child);
      child = child.parentData.previousSibling;
      assert(child.parentData is ParentDataType);
    }
    return child == equals;
  }
  bool _debugUltimateNextSiblingOf(ChildType child, { ChildType equals }) {
    assert(child.parentData is ParentDataType);
    while (child.parentData.nextSibling != null) {
      assert(child.parentData.nextSibling != child);
      child = child.parentData.nextSibling;
      assert(child.parentData is ParentDataType);
    }
    return child == equals;
  }

  ChildType _firstChild;
  ChildType _lastChild;
  void add(ChildType child, { ChildType before }) {
    assert(child != this);
    assert(before != this);
    assert(child != before);
    assert(child != _firstChild);
    assert(child != _lastChild);
    setAsChild(child);
    assert(child.parentData is ParentDataType);
    assert(child.parentData.nextSibling == null);
    assert(child.parentData.previousSibling == null);
    if (before == null) {
      // append at the end (_lastChild)
      child.parentData.previousSibling = _lastChild;
      if (_lastChild != null) {
        assert(_lastChild.parentData is ParentDataType);
        _lastChild.parentData.nextSibling = child;
      }
      _lastChild = child;
      if (_firstChild == null)
        _firstChild = child;
    } else {
      assert(_firstChild != null);
      assert(_lastChild != null);
      assert(_debugUltimatePreviousSiblingOf(before, equals: _firstChild));
      assert(_debugUltimateNextSiblingOf(before, equals: _lastChild));
      assert(before.parentData is ParentDataType);
      if (before.parentData.previousSibling == null) {
        // insert at the start (_firstChild); we'll end up with two or more children
        assert(before == _firstChild);
        child.parentData.nextSibling = before;
        before.parentData.previousSibling = child;
        _firstChild = child;
      } else {
        // insert in the middle; we'll end up with three or more children
        // set up links from child to siblings
        child.parentData.previousSibling = before.parentData.previousSibling;
        child.parentData.nextSibling = before;
        // set up links from siblings to child
        assert(child.parentData.previousSibling.parentData is ParentDataType);
        assert(child.parentData.nextSibling.parentData is ParentDataType);
        child.parentData.previousSibling.parentData.nextSibling = child;
        child.parentData.nextSibling.parentData.previousSibling = child;
        assert(before.parentData.previousSibling == child);
      }
    }
    markNeedsLayout();
  }
  void remove(ChildType child) {
    assert(child.parentData is ParentDataType);
    assert(_debugUltimatePreviousSiblingOf(child, equals: _firstChild));
    assert(_debugUltimateNextSiblingOf(child, equals: _lastChild));
    if (child.parentData.previousSibling == null) {
      assert(_firstChild == child);
      _firstChild = child.parentData.nextSibling;
    } else {
      assert(child.parentData.previousSibling.parentData is ParentDataType);
      child.parentData.previousSibling.parentData.nextSibling = child.parentData.nextSibling;
    }
    if (child.parentData.nextSibling == null) {
      assert(_lastChild == child);
      _lastChild = child.parentData.previousSibling;
    } else {
      assert(child.parentData.nextSibling.parentData is ParentDataType);
      child.parentData.nextSibling.parentData.previousSibling = child.parentData.previousSibling;
    }
    child.parentData.previousSibling = null;
    child.parentData.nextSibling = null;
    dropChild(child);
    markNeedsLayout();
  }
  void redepthChildren() {
    ChildType child = _firstChild;
    while (child != null) {
      redepthChild(child);
      assert(child.parentData is ParentDataType);
      child = child.parentData.nextSibling;
    }
  }
  void attachChildren() {
    ChildType child = _firstChild;
    while (child != null) {
      child.attach();
      assert(child.parentData is ParentDataType);
      child = child.parentData.nextSibling;
    }
  }
  void detachChildren() {
    ChildType child = _firstChild;
    while (child != null) {
      child.detach();
      assert(child.parentData is ParentDataType);
      child = child.parentData.nextSibling;
    }
  }

  ChildType get firstChild => _firstChild;
  ChildType get lastChild => _lastChild;
  ChildType childAfter(ChildType child) {
    assert(child.parentData is ParentDataType);
    return child.parentData.nextSibling;
  }

}


// CSS SHIMS

abstract class RenderCSS extends RenderBox {

  dynamic debug;
  sky.Element _skyElement;

  RenderCSS(this.debug) {
    _skyElement = createSkyElement();
    registerEventTarget(_skyElement, this);
  }

  sky.Element createSkyElement();

  void updateStyles(List<Style> styles) {
    _skyElement.setAttribute('class', styles.map((s) => s._className).join(' '));
  }

  void updateInlineStyle(String newStyle) {
    _skyElement.setAttribute('style', newStyle);
  }

  double get width {
    sky.ClientRect rect = _skyElement.getBoundingClientRect();
    return rect.width;
  }

  double get height {
    sky.ClientRect rect = _skyElement.getBoundingClientRect();
    return rect.height;
  }

  Rect get rect {
    sky.ClientRect rect = _skyElement.getBoundingClientRect();
    return new Rect(rect.left, rect.top, rect.width, rect.height);
  }

}

class CSSParentData extends ParentData with ContainerParentDataMixin<RenderCSS> { }

class RenderCSSContainer extends RenderCSS with ContainerRenderNodeMixin<RenderCSS, CSSParentData> {

  RenderCSSContainer(debug) : super(debug);

  void setupPos(RenderNode child) {
    if (child.parentData is! CSSParentData)
      child.parentData = new CSSParentData();
  }

  sky.Element createSkyElement() => sky.document.createElement('div')
                                               ..setAttribute('debug', debug.toString());

  void markNeedsLayout() { }

  void add(RenderCSS child, { RenderCSS before }) {
    if (before != null) {
      assert(before._skyElement.parentNode != null);
      assert(before._skyElement.parentNode == _skyElement);
    }
    super.add(child, before: before);
    if (before != null) {
      before._skyElement.insertBefore([child._skyElement]);
      assert(child._skyElement.parentNode != null);
      assert(child._skyElement.parentNode == _skyElement);
      assert(child._skyElement.parentNode == before._skyElement.parentNode);
    } else {
      _skyElement.appendChild(child._skyElement);
    }    
  }
  void remove(RenderCSS child) {
    child._skyElement.remove();
    super.remove(child);
  }

}

class RenderCSSText extends RenderCSS {

  RenderCSSText(debug, String newData) : super(debug) {
    data = newData;
  }

  static final Style _displayParagraph = new Style('display:paragraph');

  sky.Element createSkyElement() {
    return sky.document.createElement('div')
                      ..setChild(new sky.Text())
                      ..setAttribute('class', _displayParagraph._className)
                      ..setAttribute('debug', debug.toString());
  }

  void set data (String value) {
    (_skyElement.firstChild as sky.Text).data = value;
  }

}

class RenderCSSImage extends RenderCSS {

  RenderCSSImage(debug, String src, num width, num height) : super(debug) {
    configure(src, width, height);
  }

  sky.Element createSkyElement() {
    return sky.document.createElement('img')
                      ..setAttribute('debug', debug.toString());
  }

  void configure(String src, num width, num height) {
    if (_skyElement.getAttribute('src') != src)
      _skyElement.setAttribute('src', src);
    _skyElement.style['width'] = '${width}px';
    _skyElement.style['height'] = '${height}px';
  }

}

class RenderCSSRoot extends RenderCSSContainer {
  RenderCSSRoot(debug) : super(debug);
  sky.Element createSkyElement() {
    var result = super.createSkyElement();
    assert(result != null);
    sky.document.appendChild(result);
    return result;
  }
}


// legacy tools
Map<sky.EventTarget, RenderNode> _eventTargetRegistry = {};
void registerEventTarget(sky.EventTarget e, RenderNode n) {
  _eventTargetRegistry[e] = n;
}
RenderNode bridgeEventTargetToRenderNode(sky.EventTarget e) {
  return _eventTargetRegistry[e];
}




String _attributes(node) {
  if (node is! sky.Element) return '';
  var result = '';
  var attrs = node.getAttributes();
  for (var attr in attrs)
    result += ' ${attr.name}="${attr.value}"';
  return result;
}

void _serialiseDOM(node, [String prefix = '']) {
  if (node is sky.Text) {
    print(prefix + 'text: "' + node.data.replaceAll('\n', '\\n') + '"');
    return;
  }
  print(prefix + node.toString() + _attributes(node));
  var children = node.getChildNodes();
  prefix = prefix + '  ';
  for (var child in children)
    _serialiseDOM(child, prefix);
}

void dumpState() {
  _serialiseDOM(sky.document);
}
