text: define(function(require, exports, module) {
      var kity = require('./kity');
      var utils = require('./utils');
      var Minder = require('./minder');
  
      /**
       * @class MinderNode
       *
       * 表示一个脑图节点
       */
      var MinderNode = kity.createClass('MinderNode', {
  
          /**
           * 创建一个游离的脑图节点
           *
           * @param {String|Object} textOrData
           *     节点的初始数据或文本
           */
          constructor: function(textOrData) {
  
              // 指针
              this.parent = null;
              this.root = this;
              this.children = [];
  
              // 数据
              this.data = {
                  id: utils.guid(),
                  created: +new Date()
              };
  
              // 绘图容器
              this.initContainers();
  
              if (utils.isString(textOrData)) {
                  this.setText(textOrData);
              } else if (utils.isObject(textOrData)) {
                  utils.extend(this.data, textOrData);
              }
          },
  
          initContainers: function() {
              this.rc = new kity.Group().setId(utils.uuid('minder_node'));
              this.rc.minderNode = this;
          },
  
          /**
           * 判断节点是否根节点
           */
          isRoot: function() {
              return this.root === this;
          },
  
          /**
           * 判断节点是否叶子
           */
          isLeaf: function() {
              return this.children.length === 0;
          },
  
          /**
           * 获取节点的根节点
           */
          getRoot: function() {
              return this.root || this;
          },
  
          /**
           * 获得节点的父节点
           */
          getParent: function() {
              return this.parent;
          },
  
          getSiblings: function() {
              var children = this.parent.children;
              var siblings = [];
              var self = this;
              children.forEach(function(child) {
                  if (child != self) siblings.push(child);
              });
              return siblings;
          },
  
          /**
           * 获得节点的深度
           */
          getLevel: function() {
              var level = 0,
                  ancestor = this.parent;
              while (ancestor) {
                  level++;
                  ancestor = ancestor.parent;
              }
              return level;
          },
  
          /**
           * 获得节点的复杂度（即子树中节点的数量）
           */
          getComplex: function() {
              var complex = 0;
              this.traverse(function() {
                  complex++;
              });
              return complex;
          },
  
          /**
           * 获得节点的类型（root|main|sub）
           */
          getType: function(type) {
              this.type = ['root', 'main', 'sub'][Math.min(this.getLevel(), 2)];
              return this.type;
          },
  
          /**
           * 判断当前节点是否被测试节点的祖先
           * @param  {MinderNode}  test 被测试的节点
           */
          isAncestorOf: function(test) {
              var ancestor = test.parent;
              while (ancestor) {
                  if (ancestor == this) return true;
                  ancestor = ancestor.parent;
              }
              return false;
          },
  
          getData: function(key) {
              return key ? this.data[key] : this.data;
          },
  
          setData: function(key, value) {
              if (typeof key == 'object') {
                  var data = key;
                  for (key in data) if (data.hasOwnProperty(key)) {
                      this.data[key] = data[key];
                  }
              }
              else {
                  this.data[key] = value;
              }
              return this;
          },
  
          /**
           * 设置节点的文本数据
           * @param {String} text 文本数据
           */
          setText: function(text) {
              return this.data.text = text;
          },
  
          /**
           * 获取节点的文本数据
           * @return {String}
           */
          getText: function() {
              return this.data.text || null;
          },
  
          /**
           * 先序遍历当前节点树
           * @param  {Function} fn 遍历函数
           */
          preTraverse: function(fn, excludeThis) {
              var children = this.getChildren();
              if (!excludeThis) fn(this);
              for (var i = 0; i < children.length; i++) {
                  children[i].preTraverse(fn);
              }
          },
  
          /**
           * 后序遍历当前节点树
           * @param  {Function} fn 遍历函数
           */
          postTraverse: function(fn, excludeThis) {
              var children = this.getChildren();
              for (var i = 0; i < children.length; i++) {
                  children[i].postTraverse(fn);
              }
              if (!excludeThis) fn(this);
          },
  
          traverse: function(fn, excludeThis) {
              return this.postTraverse(fn, excludeThis);
          },
  
          getChildren: function() {
              return this.children;
          },
  
          getIndex: function() {
              return this.parent ? this.parent.children.indexOf(this) : -1;
          },
  
          insertChild: function(node, index) {
              if (index === undefined) {
                  index = this.children.length;
              }
              if (node.parent) {
                  node.parent.removeChild(node);
              }
              node.parent = this;
              node.root = this.root;
  
              this.children.splice(index, 0, node);
          },
  
          appendChild: function(node) {
              return this.insertChild(node);
          },
  
          prependChild: function(node) {
              return this.insertChild(node, 0);
          },
  
          removeChild: function(elem) {
              var index = elem,
                  removed;
              if (elem instanceof MinderNode) {
                  index = this.children.indexOf(elem);
              }
              if (index >= 0) {
                  removed = this.children.splice(index, 1)[0];
                  removed.parent = null;
                  removed.root = removed;
              }
          },
  
          clearChildren: function() {
              this.children = [];
          },
  
          getChild: function(index) {
              return this.children[index];
          },
  
          getRenderContainer: function() {
              return this.rc;
          },
  
          getCommonAncestor: function(node) {
              return MinderNode.getCommonAncestor(this, node);
          },
  
          contains: function(node) {
              return this == node || this.isAncestorOf(node);
          },
  
          clone: function() {
              var cloned = new MinderNode();
  
              cloned.data = utils.clone(this.data);
  
              this.children.forEach(function(child) {
                  cloned.appendChild(child.clone());
              });
  
              return cloned;
          },
  
          compareTo: function(node) {
  
              if (!utils.comparePlainObject(this.data, node.data)) return false;
              if (!utils.comparePlainObject(this.temp, node.temp)) return false;
              if (this.children.length != node.children.length) return false;
  
              var i = 0;
              while (this.children[i]) {
                  if (!this.children[i].compareTo(node.children[i])) return false;
                  i++;
              }
  
              return true;
          },
  
          getMinder: function() {
              return this.getRoot().minder;
          }
      });
  
      MinderNode.getCommonAncestor = function(nodeA, nodeB) {
          if (nodeA instanceof Array) {
              return MinderNode.getCommonAncestor.apply(this, nodeA);
          }
          switch (arguments.length) {
              case 1:
                  return nodeA.parent || nodeA;
  
              case 2:
                  if (nodeA.isAncestorOf(nodeB)) {
                      return nodeA;
                  }
                  if (nodeB.isAncestorOf(nodeA)) {
                      return nodeB;
                  }
                  var ancestor = nodeA.parent;
                  while (ancestor && !ancestor.isAncestorOf(nodeB)) {
                      ancestor = ancestor.parent;
                  }
                  return ancestor;
  
              default:
                  return Array.prototype.reduce.call(arguments,
                      function(prev, current) {
                          return MinderNode.getCommonAncestor(prev, current);
                      },
                      nodeA
                  );
          }
      };
  
      kity.extendClass(Minder, {
  
          getRoot: function() {
              return this._root;
          },
  
          setRoot: function(root) {
              this._root = root;
              root.minder = this;
          },
  
          getAllNode: function() {
              var nodes = [];
              this.getRoot().traverse(function(node) {
                  nodes.push(node);
              });
              return nodes;
          },
  
          getNodeById: function(id) {
              return this.getNodesById([id])[0];
          },
  
          getNodesById: function(ids) {
              var nodes = this.getAllNode();
              var result = [];
              nodes.forEach(function(node) {
                  if (ids.indexOf(node.getData('id')) != -1) {
                      result.push(node);
                  }
              });
              return result;
          },
  
          // 新建 Minder 节点
          createNode: function(textOrData, parent, index) {
              var node = new MinderNode(textOrData);
              this.fire('nodecreate', {
                  node: node,
                  parent: parent,
                  index: index
              });
              // 添加节点
              this.appendNode(node, parent, index);
              return node;
          },
  
          appendNode: function(node, parent, index) {
              if (parent) parent.insertChild(node, index);
              this.attachNode(node);
              return this;
          },
  
          removeNode: function(node) {
              if (node.parent) {
                  node.parent.removeChild(node);
                  this.detachNode(node);
                  this.fire('noderemove', {
                      node: node
                  });
              }
          },
  
          attachNode: function(node) {
              var rc = this.getRenderContainer();
              node.traverse(function(current) {
                  current.attached = true;
                  rc.addShape(current.getRenderContainer()); // 真正的生成节点
              });
              rc.addShape(node.getRenderContainer()); // 真正的生成节点
              this.fire('nodeattach', {
                  node: node
              });
          },
  
          detachNode: function(node) {
              var rc = this.getRenderContainer();
              node.traverse(function(current) {
                  current.attached = false;
                  rc.removeShape(current.getRenderContainer());
              });
              this.fire('nodedetach', {
                  node: node
              });
          },
  
          getMinderTitle: function() {
              return this.getRoot().getText();
          }
  
      });
  
      module.exports = MinderNode;
  });