/**
 * There are three basic use cases of dumpAsMarkup
 *
 * 1. Dump the entire DOM when the page is loaded
 *    When this script is included but no method of Markup is called,
 *    it dumps the DOM of each frame loaded.
 *
 * 2. Dump the content of a specific element when the page is loaded
 *    When Markup.setNodeToDump is called with some element or the id of some element,
 *    it dumps the content of the specified element as supposed to the entire DOM tree.
 *
 * 3. Dump the content of a specific element multiple times while the page is loading
 *    Calling Markup.dump would dump the content of the element set by setNodeToDump or the entire DOM.
 *    Optionally specify the node to dump and the description for each call of dump.
 */

if (window.testRunner)
    testRunner.dumpAsText();

// Namespace
// FIXME: Rename dump-as-markup.js to dump-dom.js and Markup to DOM.
var Markup = {};

// The description of what this test is testing. Gets prepended to the dumped markup.
Markup.description = function(description)
{
    Markup._test_description = description;
}

// Dumps the markup for the given node (HTML element if no node is given).
// Over-writes the body's content with the markup in layout test mode. Appends
// a pre element when loaded manually, in order to aid debugging.
Markup.dump = function(opt_node, opt_description)
{
    if (typeof opt_node == 'string')
        opt_node = document.getElementById(opt_node);

    var node = opt_node || document
    var markup = "";

    Markup._dumpCalls++;

    if (Markup._dumpCalls > 1 || opt_description) {
        if (!opt_description)
            opt_description = "Dump of markup " + Markup._dumpCalls
        if (Markup._dumpCalls > 1)
            markup += '\n';
        markup += '\n' + opt_description + ':\n';
    } else
        Markup._firstCallDidNotHaveDescription = true;

    markup += Markup.get(node);

    if (!Markup._container) {
        Markup._container = document.createElement('pre');
        Markup._container.style.width = '100%';
    }

    if (Markup._dumpCalls == 2 && Markup._firstCallDidNotHaveDescription) {
        var wrapper = Markup._container.getElementsByClassName('dump-as-markup-span')[0];
        wrapper.insertBefore(document.createTextNode('\nDump of markup 1:\n'), wrapper.firstChild);
    }

    // FIXME: Have this respect testRunner.dumpChildFramesAsText?
    // FIXME: Should we care about framesets?
    // DocumentFragment doesn't have a getElementsByTagName method.
    if (node.getElementsByTagName) {
        var iframes = node.getElementsByTagName('iframe');
        for (var i = 0; i < iframes.length; i++) {
            markup += '\n\nFRAME ' + i + ':\n'
            try {
                markup += Markup.get(iframes[i].contentDocument.body.parentElement);
            } catch (e) {
                markup += 'FIXME: Add method to layout test controller to get access to cross-origin frames.';
            }
        }
    }

    if (Markup._test_description && Markup._dumpCalls == 1)
        Markup._container.appendChild(document.createTextNode(Markup._test_description + '\n'))

    var wrapper = document.createElement('span');
    wrapper.className = 'dump-as-markup-span';
    wrapper.appendChild(document.createTextNode(markup));
    Markup._container.appendChild(wrapper);
}

Markup.noAutoDump = function()
{
    window.removeEventListener('load', Markup.notifyDone, false);
}

Markup.waitUntilDone = function()
{
    if (window.testRunner)
        testRunner.waitUntilDone();
    Markup.noAutoDump();
}

Markup.notifyDone = function()
{
    // Need to waitUntilDone or some tests won't finish appending the markup before the text is dumped.
    if (window.testRunner)
        testRunner.waitUntilDone();

    // If dump has already been called, don't bother to dump again
    if (!Markup._dumpCalls)
        Markup.dump();

    // In non-layout test mode, append the results in a pre so that we don't
    // clobber the test itself. But when in layout test mode, we don't want
    // side effects from the test to be included in the results.
    if (window.testRunner)
        document.body.innerHTML = '';

    document.body.appendChild(Markup._container);

    if (window.testRunner)
        testRunner.notifyDone();
}

Markup.useHTML5libOutputFormat = function()
{
    Markup._useHTML5libOutputFormat = true;
}

Markup.get = function(node)
{
    var shadowRootList = {};
    var markup = Markup._getShadowHostIfPossible(node, 0, shadowRootList);
    if (markup)
        return markup.substring(1);

    if (!node.firstChild)
        return '| ';

    // Don't print any markup for the root node.

    var len = node.childNodes.length;
    var i = 0;
    for (; i < len; i++) {
        markup += Markup._getSelectionMarkerWithIdentation(node, i, 0);
        markup += Markup._get(node.childNodes[i], 0, shadowRootList);
    }
    markup += Markup._getSelectionMarkerWithIdentation(node, len, 0);

    return markup.substring(1);
}

// Returns the markup for the given node. To be used for cases where a test needs
// to get the markup but not clobber the whole page.
Markup._get = function(node, depth, shadowRootList)
{
    var str = Markup._indent(depth);

    switch (node.nodeType) {
    case Node.DOCUMENT_TYPE_NODE:
        str += '<!DOCTYPE ' + node.nodeName;
        // FIXME: The actual MarkupAccumulator in WebKit handles these quite differently.
        // Should we change to match that format? Would probably need to change test results,
        // but it could help us distinguish empty strings from missing properties and
        // would include internalSubset, which this omits.
        if (node.publicId || node.systemId) {
            str += ' "' + (node.publicId || '') + '"';
            str += ' "' + (node.systemId || '') + '"';
        }
        str += '>';
        break;

    case Node.COMMENT_NODE:
        try {
            str += '<!-- ' + node.nodeValue + ' -->';
        } catch (e) {
            str += '<!--  -->';
        }
         break;

    case Node.PROCESSING_INSTRUCTION_NODE:
        str += '<?' + node.nodeName + node.nodeValue + '>';
        break;

    case Node.CDATA_SECTION_NODE:
        str += '<![CDATA[ ' + node.nodeValue + ' ]]>';
        break;

    case Node.TEXT_NODE:
        str += '"' + Markup._getMarkupForTextNode(node) + '"';
        break;

    case Node.ELEMENT_NODE:
        str += "<";
        str += Markup._namespace(node)

        if (node.localName && node.namespaceURI && node.namespaceURI != null)
            str += node.localName;
        else
            str += Markup._toAsciiLowerCase(node.nodeName);

        str += '>';

        if (node.attributes) {
            var attrNames = [];
            var attrPos = {};
            for (var j = 0; j < node.attributes.length; j += 1) {
                if (node.attributes[j].specified) {
                    var name = Markup._namespace(node.attributes[j])
                    name += node.attributes[j].localName || node.attributes[j].nodeName;
                    attrNames.push(name);
                    attrPos[name] = j;
                }
            }
            if (attrNames.length > 0) {
              attrNames.sort();
              for (var j = 0; j < attrNames.length; j += 1) {
                str += Markup._indent(depth + 1) + attrNames[j];
                str += '="' + node.attributes[attrPos[attrNames[j]]].nodeValue + '"';
              }
            }
        }

        if (!Markup._useHTML5libOutputFormat && window.internals) {
            var pseudoId = window.internals.shadowPseudoId(node);
            if (pseudoId)
                str += Markup._indent(depth + 1) + 'shadow:pseudoId="' + pseudoId + '"';
        }

        if (!Markup._useHTML5libOutputFormat)
            if (node.nodeName == "INPUT" || node.nodeName == "TEXTAREA")
                str += Markup._indent(depth + 1) + 'this.value="' + node.value + '"';

        break;
    case Node.DOCUMENT_FRAGMENT_NODE:
        if (shadowRootList && window.internals && internals.address(node) in shadowRootList)
          str += "<shadow:root>";
        else
          str += "content";
    }

    if (node.namespaceURI = 'http://www.w3.org/1999/xhtml' && node.tagName == 'TEMPLATE')
        str += Markup._get(node.content, depth + 1, shadowRootList);

    for (var i = 0, len = node.childNodes.length; i < len; i++) {
        str += Markup._getSelectionMarkerWithIdentation(node, i, depth + 1);
        str += Markup._get(node.childNodes[i], depth + 1, shadowRootList);
    }
    
    str += Markup._getShadowHostIfPossible(node, depth, shadowRootList);
    str += Markup._getSelectionMarkerWithIdentation(node, i, depth + 1);

    return str;
}

Markup._getShadowHostIfPossible = function (node, depth, shadowRootList)
{
    if (!Markup._useHTML5libOutputFormat && node.nodeType == Node.ELEMENT_NODE && window.internals) {
        var root = window.internals.shadowRoot(node);
        if (root) {
            shadowRootList[internals.address(root)] = true;
            return Markup._get(root, depth + 1, shadowRootList);
        }
    }
    return '';
}

Markup._namespace = function(node)
{
    if (Markup._NAMESPACE_URI_MAP[node.namespaceURI])
        return Markup._NAMESPACE_URI_MAP[node.namespaceURI] + ' ';
    return '';
}

Markup._dumpCalls = 0

Markup._indent = function(depth)
{
    return "\n| " + new Array(depth * 2 + 1).join(' ');
}

Markup._toAsciiLowerCase = function (str) {
  var output = "";
  for (var i = 0, len = this.length; i < len; ++i) {
    if (str.charCodeAt(i) >= 0x41 && str.charCodeAt(i) <= 0x5A)
      output += String.fromCharCode(str.charCodeAt(i) + 0x20)
    else
      output += str.charAt(i);
  }
  return output;
}

Markup._NAMESPACE_URI_MAP = {
    "http://www.w3.org/2000/svg": "svg",
    "http://www.w3.org/1998/Math/MathML": "math",
    "http://www.w3.org/XML/1998/namespace": "xml",
    "http://www.w3.org/2000/xmlns/": "xmlns",
    "http://www.w3.org/1999/xlink": "xlink"
}

Markup._getSelectionFromNode = function(node)
{
    return node.ownerDocument.defaultView ? node.ownerDocument.defaultView.getSelection() : null;
}

Markup._SELECTION_FOCUS = '<#selection-focus>';
Markup._SELECTION_ANCHOR = '<#selection-anchor>';
Markup._SELECTION_CARET = '<#selection-caret>';

Markup._getMarkupForTextNode = function(node)
{
    innerMarkup = node.nodeValue;
    var startOffset, endOffset, startText, endText;

    var sel = Markup._getSelectionFromNode(node);
    // Firefox doesn't have a sel in a display:none iframe.
    // https://bugs.webkit.org/show_bug.cgi?id=43655
    if (sel) {
        if (node == sel.anchorNode && node == sel.focusNode) {
            if (sel.isCollapsed) {
                startOffset = sel.anchorOffset;
                startText = Markup._SELECTION_CARET;
            } else {
                if (sel.focusOffset > sel.anchorOffset) {
                    startOffset = sel.anchorOffset;
                    endOffset = sel.focusOffset;
                    startText = Markup._SELECTION_ANCHOR;
                    endText = Markup._SELECTION_FOCUS;
                } else {
                    startOffset = sel.focusOffset;
                    endOffset = sel.anchorOffset;
                    startText = Markup._SELECTION_FOCUS;
                    endText = Markup._SELECTION_ANCHOR;
                }
            }
        } else if (node == sel.focusNode) {
            startOffset = sel.focusOffset;
            startText = Markup._SELECTION_FOCUS;
        } else if (node == sel.anchorNode) {
            startOffset = sel.anchorOffset;
            startText = Markup._SELECTION_ANCHOR;
        }
    }
    
    if (startText && endText)
        innerMarkup = innerMarkup.substring(0, startOffset) + startText + innerMarkup.substring(startOffset, endOffset) + endText + innerMarkup.substring(endOffset);                       
    else if (startText)
        innerMarkup = innerMarkup.substring(0, startOffset) + startText + innerMarkup.substring(startOffset);

    if (!Markup._useHTML5libOutputFormat)
        innerMarkup = innerMarkup.replace(/\\/g, "\\\\").replace(/\n/g, "\\n");

    return innerMarkup;
}

Markup._getSelectionMarkerWithIdentation = function(node, index, depth)
{
    var selection = Markup._getSelectionMarker(node, index);
    if (!selection)
        return selection;
    return Markup._indent(depth) + selection;
}

Markup._getSelectionMarker = function(node, index)
{
    if (node.nodeType != 1)
        return '';

    var sel = Markup._getSelectionFromNode(node);;

    // Firefox doesn't have a sel in a display:none iframe.
    // https://bugs.webkit.org/show_bug.cgi?id=43655
    if (!sel)
        return '';

    if (index == sel.anchorOffset && node == sel.anchorNode) {
        if (sel.isCollapsed)
            return Markup._SELECTION_CARET;
        else
            return Markup._SELECTION_ANCHOR;
    } else if (index == sel.focusOffset && node == sel.focusNode)
        return Markup._SELECTION_FOCUS;

    return '';
}

window.addEventListener('load', Markup.notifyDone, false);
