'use strict';

//Node construction exports.createDocument = function () {

return {
    nodeName: '#document',
    quirksMode: false,
    childNodes: []
};

};

exports.createDocumentFragment = function () {

return {
    nodeName: '#document-fragment',
    quirksMode: false,
    childNodes: []
};

};

exports.createElement = function (tagName, namespaceURI, attrs) {

return {
    nodeName: tagName,
    tagName: tagName,
    attrs: attrs,
    namespaceURI: namespaceURI,
    childNodes: [],
    parentNode: null
};

};

exports.createCommentNode = function (data) {

return {
    nodeName: '#comment',
    data: data,
    parentNode: null
};

};

var createTextNode = function (value) {

return {
    nodeName: '#text',
    value: value,
    parentNode: null
}

};

//Tree mutation exports.setDocumentType = function (document, name, publicId, systemId) {

var doctypeNode = null;
for (var i = 0; i < document.childNodes.length; i++) {
    if (document.childNodes[i].nodeName === '#documentType') {
        doctypeNode = document.childNodes[i];
        break;
    }
}
if (doctypeNode) {
    doctypeNode.name = name;
    doctypeNode.publicId = publicId;
    doctypeNode.systemId = systemId;
}
else {
    appendChild(document, {
        nodeName: '#documentType',
        name: name,
        publicId: publicId,
        systemId: systemId
    });
}

};

exports.setQuirksMode = function (document) {

document.quirksMode = true;

};

exports.isQuirksMode = function (document) {

return document.quirksMode;

};

var appendChild = exports.appendChild = function (parentNode, newNode) {

parentNode.childNodes.push(newNode);
newNode.parentNode = parentNode;

};

var insertBefore = exports.insertBefore = function (parentNode, newNode, referenceNode) {

var insertionIdx = parentNode.childNodes.indexOf(referenceNode);
parentNode.childNodes.splice(insertionIdx, 0, newNode);
newNode.parentNode = parentNode;

};

exports.detachNode = function (node) {

if (node.parentNode) {
    var idx = node.parentNode.childNodes.indexOf(node);
    node.parentNode.childNodes.splice(idx, 1);
    node.parentNode = null;
}

};

exports.insertText = function (parentNode, text) {

if (parentNode.childNodes.length) {
    var prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
    if (prevNode.nodeName === '#text') {
        prevNode.value += text;
        return;
    }
}
appendChild(parentNode, createTextNode(text));

};

exports.insertTextBefore = function (parentNode, text, referenceNode) {

var prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
if (prevNode && prevNode.nodeName === '#text')
    prevNode.value += text;
else
    insertBefore(parentNode, createTextNode(text), referenceNode);

};

exports.adoptAttributes = function (recipientNode, attrs) {

var recipientAttrsMap = [];
for (var i = 0; i < recipientNode.attrs.length; i++)
    recipientAttrsMap.push(recipientNode.attrs[i].name);
for (var j = 0; j < attrs.length; j++) {
    if (recipientAttrsMap.indexOf(attrs[j].name) === -1)
        recipientNode.attrs.push(attrs[j]);
}

};

//Tree traversing exports.getFirstChild = function (node) {

return node.childNodes[0];

};

exports.getChildNodes = function (node) {

return node.childNodes;

};

exports.getParentNode = function (node) {

return node.parentNode;

};

exports.getAttrList = function (node) {

return node.attrs;

};

//Node data exports.getTagName = function (element) {

return element.tagName;

};

exports.getNamespaceURI = function (element) {

return element.namespaceURI;

};

exports.getTextNodeContent = function (textNode) {

return textNode.value;

};

exports.getCommentNodeContent = function (commentNode) {

return commentNode.data;

};

exports.getDocumentTypeNodeName = function (doctypeNode) {

return doctypeNode.name;

};

exports.getDocumentTypeNodePublicId = function (doctypeNode) {

return doctypeNode.publicId;

};

exports.getDocumentTypeNodeSystemId = function (doctypeNode) {

return doctypeNode.systemId;

};

//Node types exports.isTextNode = function (node) {

return node.nodeName === '#text';

};

exports.isCommentNode = function (node) {

return node.nodeName === '#comment';

};

exports.isDocumentTypeNode = function (node) {

return node.nodeName === '#documentType';

};

exports.isElementNode = function (node) {

return !!node.tagName;

};