/*
 * Copyright (C) 2011 Google Inc.  All rights reserved.
 * Copyright (C) 2007, 2008 Apple Inc.  All rights reserved.
 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
Components.DOMPresentationUtils = {};

/**
 * @param {!SDK.DOMNode} node
 * @param {!Element} parentElement
 * @param {string=} tooltipContent
 */
Components.DOMPresentationUtils.decorateNodeLabel = function(node, parentElement, tooltipContent) {
  var originalNode = node;
  var isPseudo = node.nodeType() === Node.ELEMENT_NODE && node.pseudoType();
  if (isPseudo && node.parentNode)
    node = node.parentNode;

  var title = node.nodeNameInCorrectCase();

  var nameElement = parentElement.createChild('span', 'node-label-name');
  nameElement.textContent = title;

  var idAttribute = node.getAttribute('id');
  if (idAttribute) {
    var idElement = parentElement.createChild('span', 'node-label-id');
    var part = '#' + idAttribute;
    title += part;
    idElement.createTextChild(part);

    // Mark the name as extra, since the ID is more important.
    nameElement.classList.add('extra');
  }

  var classAttribute = node.getAttribute('class');
  if (classAttribute) {
    var classes = classAttribute.split(/\s+/);
    var foundClasses = {};

    if (classes.length) {
      var classesElement = parentElement.createChild('span', 'extra node-label-class');
      for (var i = 0; i < classes.length; ++i) {
        var className = classes[i];
        if (className && !(className in foundClasses)) {
          var part = '.' + className;
          title += part;
          classesElement.createTextChild(part);
          foundClasses[className] = true;
        }
      }
    }
  }

  if (isPseudo) {
    var pseudoElement = parentElement.createChild('span', 'extra node-label-pseudo');
    var pseudoText = '::' + originalNode.pseudoType();
    pseudoElement.createTextChild(pseudoText);
    title += pseudoText;
  }
  parentElement.title = tooltipContent || title;
};

/**
 * @param {!Element} container
 * @param {string} nodeTitle
 */
Components.DOMPresentationUtils.createSpansForNodeTitle = function(container, nodeTitle) {
  var match = nodeTitle.match(/([^#.]+)(#[^.]+)?(\..*)?/);
  container.createChild('span', 'webkit-html-tag-name').textContent = match[1];
  if (match[2])
    container.createChild('span', 'webkit-html-attribute-value').textContent = match[2];
  if (match[3])
    container.createChild('span', 'webkit-html-attribute-name').textContent = match[3];
};

/**
 * @param {?SDK.DOMNode} node
 * @param {string=} idref
 * @param {string=} tooltipContent
 * @return {!Node}
 */
Components.DOMPresentationUtils.linkifyNodeReference = function(node, idref, tooltipContent) {
  if (!node)
    return createTextNode(Common.UIString('<node>'));

  var root = createElementWithClass('span', 'monospace');
  var shadowRoot = UI.createShadowRootWithCoreStyles(root, 'components/domUtils.css');
  var link = shadowRoot.createChild('div', 'node-link');

  if (idref)
    link.createChild('span', 'node-label-id').createTextChild('#' + idref);
  else
    Components.DOMPresentationUtils.decorateNodeLabel(node, link, tooltipContent);

  link.addEventListener('click', Common.Revealer.reveal.bind(Common.Revealer, node, undefined), false);
  link.addEventListener('mouseover', node.highlight.bind(node, undefined, undefined), false);
  link.addEventListener('mouseleave', () => SDK.OverlayModel.hideDOMNodeHighlight(), false);

  return root;
};

/**
 * @param {!SDK.DeferredDOMNode} deferredNode
 * @return {!Node}
 */
Components.DOMPresentationUtils.linkifyDeferredNodeReference = function(deferredNode) {
  var root = createElement('div');
  var shadowRoot = UI.createShadowRootWithCoreStyles(root, 'components/domUtils.css');
  var link = shadowRoot.createChild('div', 'node-link');
  link.createChild('content');
  link.addEventListener('click', deferredNode.resolve.bind(deferredNode, onDeferredNodeResolved), false);
  link.addEventListener('mousedown', e => e.consume(), false);

  /**
   * @param {?SDK.DOMNode} node
   */
  function onDeferredNodeResolved(node) {
    Common.Revealer.reveal(node);
  }

  return root;
};

/**
 * @param {!SDK.Target} target
 * @param {string} originalImageURL
 * @param {boolean} showDimensions
 * @param {!Object=} precomputedFeatures
 * @return {!Promise<?Element>}
 */
Components.DOMPresentationUtils.buildImagePreviewContents = function(
    target, originalImageURL, showDimensions, precomputedFeatures) {
  var resourceTreeModel = target.model(SDK.ResourceTreeModel);
  if (!resourceTreeModel)
    return Promise.resolve(/** @type {?Element} */ (null));
  var resource = resourceTreeModel.resourceForURL(originalImageURL);
  var imageURL = originalImageURL;
  if (!isImageResource(resource) && precomputedFeatures && precomputedFeatures.currentSrc) {
    imageURL = precomputedFeatures.currentSrc;
    resource = resourceTreeModel.resourceForURL(imageURL);
  }
  if (!isImageResource(resource))
    return Promise.resolve(/** @type {?Element} */ (null));

  var fulfill;
  var promise = new Promise(x => fulfill = x);
  var imageElement = createElement('img');
  imageElement.addEventListener('load', buildContent, false);
  imageElement.addEventListener('error', () => fulfill(null), false);
  resource.populateImageSource(imageElement);
  return promise;

  /**
   * @param {?SDK.Resource} resource
   * @return {boolean}
   */
  function isImageResource(resource) {
    return !!resource && resource.resourceType() === Common.resourceTypes.Image;
  }

  function buildContent() {
    var container = createElement('table');
    UI.appendStyle(container, 'components/imagePreview.css');
    container.className = 'image-preview-container';
    var naturalWidth = precomputedFeatures ? precomputedFeatures.naturalWidth : imageElement.naturalWidth;
    var naturalHeight = precomputedFeatures ? precomputedFeatures.naturalHeight : imageElement.naturalHeight;
    var offsetWidth = precomputedFeatures ? precomputedFeatures.offsetWidth : naturalWidth;
    var offsetHeight = precomputedFeatures ? precomputedFeatures.offsetHeight : naturalHeight;
    var description;
    if (showDimensions) {
      if (offsetHeight === naturalHeight && offsetWidth === naturalWidth) {
        description = Common.UIString('%d \xd7 %d pixels', offsetWidth, offsetHeight);
      } else {
        description = Common.UIString(
            '%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)', offsetWidth, offsetHeight, naturalWidth, naturalHeight);
      }
    }

    container.createChild('tr').createChild('td', 'image-container').appendChild(imageElement);
    if (description)
      container.createChild('tr').createChild('td').createChild('span', 'description').textContent = description;
    if (imageURL !== originalImageURL) {
      container.createChild('tr').createChild('td').createChild('span', 'description').textContent =
          String.sprintf('currentSrc: %s', imageURL.trimMiddle(100));
    }
    fulfill(container);
  }
};

/**
 * @param {?SDK.Target} target
 * @param {!Components.Linkifier} linkifier
 * @param {!Protocol.Runtime.StackTrace=} stackTrace
 * @param {function()=} contentUpdated
 * @return {!Element}
 */
Components.DOMPresentationUtils.buildStackTracePreviewContents = function(
    target, linkifier, stackTrace, contentUpdated) {
  var element = createElement('span');
  element.style.display = 'inline-block';
  var shadowRoot = UI.createShadowRootWithCoreStyles(element, 'components/domUtils.css');
  var contentElement = shadowRoot.createChild('table', 'stack-preview-container');
  var debuggerModel = target ? target.model(SDK.DebuggerModel) : null;
  var totalHiddenCallFramesCount = 0;

  /**
   * @param {!Protocol.Runtime.StackTrace} stackTrace
   * @return {boolean}
   */
  function appendStackTrace(stackTrace) {
    var hiddenCallFrames = 0;
    for (var stackFrame of stackTrace.callFrames) {
      var row = createElement('tr');
      row.createChild('td').textContent = '\n';
      row.createChild('td', 'function-name').textContent = UI.beautifyFunctionName(stackFrame.functionName);
      var link = linkifier.maybeLinkifyConsoleCallFrame(target, stackFrame);
      if (link) {
        link.addEventListener('contextmenu', populateContextMenu.bind(null, link));
        if (debuggerModel) {
          var location = debuggerModel.createRawLocationByScriptId(
              stackFrame.scriptId, stackFrame.lineNumber, stackFrame.columnNumber);
          if (location && Bindings.blackboxManager.isBlackboxedRawLocation(location)) {
            row.classList.add('blackboxed');
            ++hiddenCallFrames;
          }
        }

        row.createChild('td').textContent = ' @ ';
        row.createChild('td').appendChild(link);
      }
      contentElement.appendChild(row);
    }
    totalHiddenCallFramesCount += hiddenCallFrames;
    return stackTrace.callFrames.length === hiddenCallFrames;
  }

  /**
   * @param {!Element} link
   * @param {!Event} event
   */
  function populateContextMenu(link, event) {
    var contextMenu = new UI.ContextMenu(event);
    event.consume(true);
    var uiLocation = Components.Linkifier.uiLocation(link);
    if (uiLocation && Bindings.blackboxManager.canBlackboxUISourceCode(uiLocation.uiSourceCode)) {
      if (Bindings.blackboxManager.isBlackboxedUISourceCode(uiLocation.uiSourceCode)) {
        contextMenu.debugSection().appendItem(
            ls`Stop blackboxing`, () => Bindings.blackboxManager.unblackboxUISourceCode(uiLocation.uiSourceCode));
      } else {
        contextMenu.debugSection().appendItem(
            ls`Blackbox script`, () => Bindings.blackboxManager.blackboxUISourceCode(uiLocation.uiSourceCode));
      }
    }
    contextMenu.appendApplicableItems(event);
    contextMenu.show();
  }

  if (!stackTrace)
    return element;

  appendStackTrace(stackTrace);

  var asyncStackTrace = stackTrace.parent;
  while (asyncStackTrace) {
    if (!asyncStackTrace.callFrames.length) {
      asyncStackTrace = asyncStackTrace.parent;
      continue;
    }
    var row = contentElement.createChild('tr');
    row.createChild('td').textContent = '\n';
    row.createChild('td', 'stack-preview-async-description').textContent =
        UI.asyncStackTraceLabel(asyncStackTrace.description);
    row.createChild('td');
    row.createChild('td');
    if (appendStackTrace(asyncStackTrace))
      row.classList.add('blackboxed');
    asyncStackTrace = asyncStackTrace.parent;
  }

  if (totalHiddenCallFramesCount) {
    var row = contentElement.createChild('tr', 'show-blackboxed-link');
    row.createChild('td').textContent = '\n';
    var cell = row.createChild('td');
    cell.colSpan = 4;
    var showAllLink = cell.createChild('span', 'link');
    if (totalHiddenCallFramesCount === 1)
      showAllLink.textContent = ls`Show 1 more blackboxed frame`;
    else
      showAllLink.textContent = ls`Show ${totalHiddenCallFramesCount} more blackboxed frames`;
    showAllLink.addEventListener('click', () => {
      contentElement.classList.add('show-blackboxed');
      if (contentUpdated)
        contentUpdated();
    }, false);
  }

  return element;
};

/**
 * @param {!SDK.DOMNode} node
 * @param {boolean=} justSelector
 * @return {string}
 */
Components.DOMPresentationUtils.fullQualifiedSelector = function(node, justSelector) {
  if (node.nodeType() !== Node.ELEMENT_NODE)
    return node.localName() || node.nodeName().toLowerCase();
  return Components.DOMPresentationUtils.cssPath(node, justSelector);
};

/**
 * @param {!SDK.DOMNode} node
 * @return {string}
 */
Components.DOMPresentationUtils.simpleSelector = function(node) {
  var lowerCaseName = node.localName() || node.nodeName().toLowerCase();
  if (node.nodeType() !== Node.ELEMENT_NODE)
    return lowerCaseName;
  if (lowerCaseName === 'input' && node.getAttribute('type') && !node.getAttribute('id') && !node.getAttribute('class'))
    return lowerCaseName + '[type="' + node.getAttribute('type') + '"]';
  if (node.getAttribute('id'))
    return lowerCaseName + '#' + node.getAttribute('id');
  if (node.getAttribute('class')) {
    return (lowerCaseName === 'div' ? '' : lowerCaseName) + '.' +
        node.getAttribute('class').trim().replace(/\s+/g, '.');
  }
  return lowerCaseName;
};

/**
 * @param {!SDK.DOMNode} node
 * @param {boolean=} optimized
 * @return {string}
 */
Components.DOMPresentationUtils.cssPath = function(node, optimized) {
  if (node.nodeType() !== Node.ELEMENT_NODE)
    return '';

  var steps = [];
  var contextNode = node;
  while (contextNode) {
    var step = Components.DOMPresentationUtils._cssPathStep(contextNode, !!optimized, contextNode === node);
    if (!step)
      break;  // Error - bail out early.
    steps.push(step);
    if (step.optimized)
      break;
    contextNode = contextNode.parentNode;
  }

  steps.reverse();
  return steps.join(' > ');
};

/**
 * @param {!SDK.DOMNode} node
 * @param {boolean} optimized
 * @param {boolean} isTargetNode
 * @return {?Components.DOMNodePathStep}
 */
Components.DOMPresentationUtils._cssPathStep = function(node, optimized, isTargetNode) {
  if (node.nodeType() !== Node.ELEMENT_NODE)
    return null;

  var id = node.getAttribute('id');
  if (optimized) {
    if (id)
      return new Components.DOMNodePathStep(idSelector(id), true);
    var nodeNameLower = node.nodeName().toLowerCase();
    if (nodeNameLower === 'body' || nodeNameLower === 'head' || nodeNameLower === 'html')
      return new Components.DOMNodePathStep(node.nodeNameInCorrectCase(), true);
  }
  var nodeName = node.nodeNameInCorrectCase();

  if (id)
    return new Components.DOMNodePathStep(nodeName + idSelector(id), true);
  var parent = node.parentNode;
  if (!parent || parent.nodeType() === Node.DOCUMENT_NODE)
    return new Components.DOMNodePathStep(nodeName, true);

  /**
   * @param {!SDK.DOMNode} node
   * @return {!Array.<string>}
   */
  function prefixedElementClassNames(node) {
    var classAttribute = node.getAttribute('class');
    if (!classAttribute)
      return [];

    return classAttribute.split(/\s+/g).filter(Boolean).map(function(name) {
      // The prefix is required to store "__proto__" in a object-based map.
      return '$' + name;
    });
  }

  /**
   * @param {string} id
   * @return {string}
   */
  function idSelector(id) {
    return '#' + escapeIdentifierIfNeeded(id);
  }

  /**
   * @param {string} ident
   * @return {string}
   */
  function escapeIdentifierIfNeeded(ident) {
    if (isCSSIdentifier(ident))
      return ident;
    var shouldEscapeFirst = /^(?:[0-9]|-[0-9-]?)/.test(ident);
    var lastIndex = ident.length - 1;
    return ident.replace(/./g, function(c, i) {
      return ((shouldEscapeFirst && i === 0) || !isCSSIdentChar(c)) ? escapeAsciiChar(c, i === lastIndex) : c;
    });
  }

  /**
   * @param {string} c
   * @param {boolean} isLast
   * @return {string}
   */
  function escapeAsciiChar(c, isLast) {
    return '\\' + toHexByte(c) + (isLast ? '' : ' ');
  }

  /**
   * @param {string} c
   */
  function toHexByte(c) {
    var hexByte = c.charCodeAt(0).toString(16);
    if (hexByte.length === 1)
      hexByte = '0' + hexByte;
    return hexByte;
  }

  /**
   * @param {string} c
   * @return {boolean}
   */
  function isCSSIdentChar(c) {
    if (/[a-zA-Z0-9_-]/.test(c))
      return true;
    return c.charCodeAt(0) >= 0xA0;
  }

  /**
   * @param {string} value
   * @return {boolean}
   */
  function isCSSIdentifier(value) {
    // Double hyphen prefixes are not allowed by specification, but many sites use it.
    return /^-{0,2}[a-zA-Z_][a-zA-Z0-9_-]*$/.test(value);
  }

  var prefixedOwnClassNamesArray = prefixedElementClassNames(node);
  var needsClassNames = false;
  var needsNthChild = false;
  var ownIndex = -1;
  var elementIndex = -1;
  var siblings = parent.children();
  for (var i = 0; (ownIndex === -1 || !needsNthChild) && i < siblings.length; ++i) {
    var sibling = siblings[i];
    if (sibling.nodeType() !== Node.ELEMENT_NODE)
      continue;
    elementIndex += 1;
    if (sibling === node) {
      ownIndex = elementIndex;
      continue;
    }
    if (needsNthChild)
      continue;
    if (sibling.nodeNameInCorrectCase() !== nodeName)
      continue;

    needsClassNames = true;
    var ownClassNames = new Set(prefixedOwnClassNamesArray);
    if (!ownClassNames.size) {
      needsNthChild = true;
      continue;
    }
    var siblingClassNamesArray = prefixedElementClassNames(sibling);
    for (var j = 0; j < siblingClassNamesArray.length; ++j) {
      var siblingClass = siblingClassNamesArray[j];
      if (!ownClassNames.has(siblingClass))
        continue;
      ownClassNames.delete(siblingClass);
      if (!ownClassNames.size) {
        needsNthChild = true;
        break;
      }
    }
  }

  var result = nodeName;
  if (isTargetNode && nodeName.toLowerCase() === 'input' && node.getAttribute('type') && !node.getAttribute('id') &&
      !node.getAttribute('class'))
    result += '[type="' + node.getAttribute('type') + '"]';
  if (needsNthChild) {
    result += ':nth-child(' + (ownIndex + 1) + ')';
  } else if (needsClassNames) {
    for (var prefixedName of prefixedOwnClassNamesArray)
      result += '.' + escapeIdentifierIfNeeded(prefixedName.substr(1));
  }

  return new Components.DOMNodePathStep(result, false);
};

/**
 * @param {!SDK.DOMNode} node
 * @param {boolean=} optimized
 * @return {string}
 */
Components.DOMPresentationUtils.xPath = function(node, optimized) {
  if (node.nodeType() === Node.DOCUMENT_NODE)
    return '/';

  var steps = [];
  var contextNode = node;
  while (contextNode) {
    var step = Components.DOMPresentationUtils._xPathValue(contextNode, optimized);
    if (!step)
      break;  // Error - bail out early.
    steps.push(step);
    if (step.optimized)
      break;
    contextNode = contextNode.parentNode;
  }

  steps.reverse();
  return (steps.length && steps[0].optimized ? '' : '/') + steps.join('/');
};

/**
 * @param {!SDK.DOMNode} node
 * @param {boolean=} optimized
 * @return {?Components.DOMNodePathStep}
 */
Components.DOMPresentationUtils._xPathValue = function(node, optimized) {
  var ownValue;
  var ownIndex = Components.DOMPresentationUtils._xPathIndex(node);
  if (ownIndex === -1)
    return null;  // Error.

  switch (node.nodeType()) {
    case Node.ELEMENT_NODE:
      if (optimized && node.getAttribute('id'))
        return new Components.DOMNodePathStep('//*[@id="' + node.getAttribute('id') + '"]', true);
      ownValue = node.localName();
      break;
    case Node.ATTRIBUTE_NODE:
      ownValue = '@' + node.nodeName();
      break;
    case Node.TEXT_NODE:
    case Node.CDATA_SECTION_NODE:
      ownValue = 'text()';
      break;
    case Node.PROCESSING_INSTRUCTION_NODE:
      ownValue = 'processing-instruction()';
      break;
    case Node.COMMENT_NODE:
      ownValue = 'comment()';
      break;
    case Node.DOCUMENT_NODE:
      ownValue = '';
      break;
    default:
      ownValue = '';
      break;
  }

  if (ownIndex > 0)
    ownValue += '[' + ownIndex + ']';

  return new Components.DOMNodePathStep(ownValue, node.nodeType() === Node.DOCUMENT_NODE);
};

/**
 * @param {!SDK.DOMNode} node
 * @return {number}
 */
Components.DOMPresentationUtils._xPathIndex = function(node) {
  // Returns -1 in case of error, 0 if no siblings matching the same expression, <XPath index among the same expression-matching sibling nodes> otherwise.
  function areNodesSimilar(left, right) {
    if (left === right)
      return true;

    if (left.nodeType() === Node.ELEMENT_NODE && right.nodeType() === Node.ELEMENT_NODE)
      return left.localName() === right.localName();

    if (left.nodeType() === right.nodeType())
      return true;

    // XPath treats CDATA as text nodes.
    var leftType = left.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left.nodeType();
    var rightType = right.nodeType() === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right.nodeType();
    return leftType === rightType;
  }

  var siblings = node.parentNode ? node.parentNode.children() : null;
  if (!siblings)
    return 0;  // Root node - no siblings.
  var hasSameNamedElements;
  for (var i = 0; i < siblings.length; ++i) {
    if (areNodesSimilar(node, siblings[i]) && siblings[i] !== node) {
      hasSameNamedElements = true;
      break;
    }
  }
  if (!hasSameNamedElements)
    return 0;
  var ownIndex = 1;  // XPath indices start with 1.
  for (var i = 0; i < siblings.length; ++i) {
    if (areNodesSimilar(node, siblings[i])) {
      if (siblings[i] === node)
        return ownIndex;
      ++ownIndex;
    }
  }
  return -1;  // An error occurred: |node| not found in parent's children.
};

/**
 * @unrestricted
 */
Components.DOMNodePathStep = class {
  /**
   * @param {string} value
   * @param {boolean} optimized
   */
  constructor(value, optimized) {
    this.value = value;
    this.optimized = optimized || false;
  }

  /**
   * @override
   * @return {string}
   */
  toString() {
    return this.value;
  }
};

/**
 * @interface
 */
Components.DOMPresentationUtils.MarkerDecorator = function() {};

Components.DOMPresentationUtils.MarkerDecorator.prototype = {
  /**
   * @param {!SDK.DOMNode} node
   * @return {?{title: string, color: string}}
   */
  decorate(node) {}
};

/**
 * @implements {Components.DOMPresentationUtils.MarkerDecorator}
 * @unrestricted
 */
Components.DOMPresentationUtils.GenericDecorator = class {
  /**
   * @param {!Runtime.Extension} extension
   */
  constructor(extension) {
    this._title = Common.UIString(extension.title());
    this._color = extension.descriptor()['color'];
  }

  /**
   * @override
   * @param {!SDK.DOMNode} node
   * @return {?{title: string, color: string}}
   */
  decorate(node) {
    return {title: this._title, color: this._color};
  }
};
