// Generated by CoffeeScript 1.10.0
(function () {
    var XMLCData, XMLComment, XMLDTDAttList, XMLDTDElement, XMLDTDEntity, XMLDTDNotation, XMLDeclaration, XMLDocType, XMLElement, XMLProcessingInstruction, XMLRaw, XMLStringWriter, XMLText, XMLWriterBase,
        extend = function (child, parent) {
            for (var key in parent) {
                if (hasProp.call(parent, key)) child[key] = parent[key];
            }
            function ctor() {
                this.constructor = child;
            }

            ctor.prototype = parent.prototype;
            child.prototype = new ctor();
            child.__super__ = parent.prototype;
            return child;
        },
        hasProp = {}.hasOwnProperty;

    XMLDeclaration = require('./XMLDeclaration');

    XMLDocType = require('./XMLDocType');

    XMLCData = require('./XMLCData');

    XMLComment = require('./XMLComment');

    XMLElement = require('./XMLElement');

    XMLRaw = require('./XMLRaw');

    XMLText = require('./XMLText');

    XMLProcessingInstruction = require('./XMLProcessingInstruction');

    XMLDTDAttList = require('./XMLDTDAttList');

    XMLDTDElement = require('./XMLDTDElement');

    XMLDTDEntity = require('./XMLDTDEntity');

    XMLDTDNotation = require('./XMLDTDNotation');

    XMLWriterBase = require('./XMLWriterBase');

    module.exports = XMLStringWriter = (function (superClass) {
        extend(XMLStringWriter, superClass);

        function XMLStringWriter(options) {
            XMLStringWriter.__super__.constructor.call(this, options);
        }

        XMLStringWriter.prototype.document = function (doc) {
            var child, i, len, r, ref;
            r = '';
            ref = doc.children;
            for (i = 0, len = ref.length; i < len; i++) {
                child = ref[i];
                r += (function () {
                    switch (false) {
                        case !(child instanceof XMLDeclaration):
                            return this.declaration(child);
                        case !(child instanceof XMLDocType):
                            return this.docType(child);
                        case !(child instanceof XMLComment):
                            return this.comment(child);
                        case !(child instanceof XMLProcessingInstruction):
                            return this.processingInstruction(child);
                        default:
                            return this.element(child, 0);
                    }
                }).call(this);
            }
            if (this.pretty && r.slice(-this.newline.length) === this.newline) {
                r = r.slice(0, -this.newline.length);
            }
            return r;
        };

        XMLStringWriter.prototype.attribute = function (att) {
            return ' ' + att.name + '="' + att.value + '"';
        };

        XMLStringWriter.prototype.cdata = function (node, level) {
            return this.space(level) + '<![CDATA[' + node.text + ']]>' + this.newline;
        };

        XMLStringWriter.prototype.comment = function (node, level) {
            return this.space(level) + '<!-- ' + node.text + ' -->' + this.newline;
        };

        XMLStringWriter.prototype.declaration = function (node, level) {
            var r;
            r = this.space(level);
            r += '<?xml version="' + node.version + '"';
            if (node.encoding != null) {
                r += ' encoding="' + node.encoding + '"';
            }
            if (node.standalone != null) {
                r += ' standalone="' + node.standalone + '"';
            }
            r += '?>';
            r += this.newline;
            return r;
        };

        XMLStringWriter.prototype.docType = function (node, level) {
            var child, i, len, r, ref;
            level || (level = 0);
            r = this.space(level);
            r += '<!DOCTYPE ' + node.root().name;
            if (node.pubID && node.sysID) {
                r += ' PUBLIC "' + node.pubID + '" "' + node.sysID + '"';
            } else if (node.sysID) {
                r += ' SYSTEM "' + node.sysID + '"';
            }
            if (node.children.length > 0) {
                r += ' [';
                r += this.newline;
                ref = node.children;
                for (i = 0, len = ref.length; i < len; i++) {
                    child = ref[i];
                    r += (function () {
                        switch (false) {
                            case !(child instanceof XMLDTDAttList):
                                return this.dtdAttList(child, level + 1);
                            case !(child instanceof XMLDTDElement):
                                return this.dtdElement(child, level + 1);
                            case !(child instanceof XMLDTDEntity):
                                return this.dtdEntity(child, level + 1);
                            case !(child instanceof XMLDTDNotation):
                                return this.dtdNotation(child, level + 1);
                            case !(child instanceof XMLCData):
                                return this.cdata(child, level + 1);
                            case !(child instanceof XMLComment):
                                return this.comment(child, level + 1);
                            case !(child instanceof XMLProcessingInstruction):
                                return this.processingInstruction(child, level + 1);
                            default:
                                throw new Error("Unknown DTD node type: " + child.constructor.name);
                        }
                    }).call(this);
                }
                r += ']';
            }
            r += '>';
            r += this.newline;
            return r;
        };

        XMLStringWriter.prototype.element = function (node, level) {
            var att, child, i, len, name, r, ref, ref1, space;
            level || (level = 0);
            space = this.space(level);
            r = '';
            r += space + '<' + node.name;
            ref = node.attributes;
            for (name in ref) {
                if (!hasProp.call(ref, name)) continue;
                att = ref[name];
                r += this.attribute(att);
            }
            if (node.children.length === 0 || node.children.every(function (e) {
                    return e.value === '';
                })) {
                if (this.allowEmpty) {
                    r += '></' + node.name + '>' + this.newline;
                } else {
                    r += '/>' + this.newline;
                }
            } else if (this.pretty && node.children.length === 1 && (node.children[0].value != null)) {
                r += '>';
                r += node.children[0].value;
                r += '</' + node.name + '>' + this.newline;
            } else {
                r += '>' + this.newline;
                ref1 = node.children;
                for (i = 0, len = ref1.length; i < len; i++) {
                    child = ref1[i];
                    r += (function () {
                        switch (false) {
                            case !(child instanceof XMLCData):
                                return this.cdata(child, level + 1);
                            case !(child instanceof XMLComment):
                                return this.comment(child, level + 1);
                            case !(child instanceof XMLElement):
                                return this.element(child, level + 1);
                            case !(child instanceof XMLRaw):
                                return this.raw(child, level + 1);
                            case !(child instanceof XMLText):
                                return this.text(child, level + 1);
                            case !(child instanceof XMLProcessingInstruction):
                                return this.processingInstruction(child, level + 1);
                            default:
                                throw new Error("Unknown XML node type: " + child.constructor.name);
                        }
                    }).call(this);
                }
                r += space + '</' + node.name + '>' + this.newline;
            }
            return r;
        };

        XMLStringWriter.prototype.processingInstruction = function (node, level) {
            var r;
            r = this.space(level) + '<?' + node.target;
            if (node.value) {
                r += ' ' + node.value;
            }
            r += '?>' + this.newline;
            return r;
        };

        XMLStringWriter.prototype.raw = function (node, level) {
            return this.space(level) + node.value + this.newline;
        };

        XMLStringWriter.prototype.text = function (node, level) {
            return this.space(level) + node.value + this.newline;
        };

        XMLStringWriter.prototype.dtdAttList = function (node, level) {
            var r;
            r = this.space(level) + '<!ATTLIST ' + node.elementName + ' ' + node.attributeName + ' ' + node.attributeType;
            if (node.defaultValueType !== '#DEFAULT') {
                r += ' ' + node.defaultValueType;
            }
            if (node.defaultValue) {
                r += ' "' + node.defaultValue + '"';
            }
            r += '>' + this.newline;
            return r;
        };

        XMLStringWriter.prototype.dtdElement = function (node, level) {
            return this.space(level) + '<!ELEMENT ' + node.name + ' ' + node.value + '>' + this.newline;
        };

        XMLStringWriter.prototype.dtdEntity = function (node, level) {
            var r;
            r = this.space(level) + '<!ENTITY';
            if (node.pe) {
                r += ' %';
            }
            r += ' ' + node.name;
            if (node.value) {
                r += ' "' + node.value + '"';
            } else {
                if (node.pubID && node.sysID) {
                    r += ' PUBLIC "' + node.pubID + '" "' + node.sysID + '"';
                } else if (node.sysID) {
                    r += ' SYSTEM "' + node.sysID + '"';
                }
                if (node.nData) {
                    r += ' NDATA ' + node.nData;
                }
            }
            r += '>' + this.newline;
            return r;
        };

        XMLStringWriter.prototype.dtdNotation = function (node, level) {
            var r;
            r = this.space(level) + '<!NOTATION ' + node.name;
            if (node.pubID && node.sysID) {
                r += ' PUBLIC "' + node.pubID + '" "' + node.sysID + '"';
            } else if (node.pubID) {
                r += ' PUBLIC "' + node.pubID + '"';
            } else if (node.sysID) {
                r += ' SYSTEM "' + node.sysID + '"';
            }
            r += '>' + this.newline;
            return r;
        };

        XMLStringWriter.prototype.openNode = function (node, level) {
            var att, name, r, ref;
            level || (level = 0);
            if (node instanceof XMLElement) {
                r = this.space(level) + '<' + node.name;
                ref = node.attributes;
                for (name in ref) {
                    if (!hasProp.call(ref, name)) continue;
                    att = ref[name];
                    r += this.attribute(att);
                }
                r += (node.children ? '>' : '/>') + this.newline;
                return r;
            } else {
                r = this.space(level) + '<!DOCTYPE ' + node.rootNodeName;
                if (node.pubID && node.sysID) {
                    r += ' PUBLIC "' + node.pubID + '" "' + node.sysID + '"';
                } else if (node.sysID) {
                    r += ' SYSTEM "' + node.sysID + '"';
                }
                r += (node.children ? ' [' : '>') + this.newline;
                return r;
            }
        };

        XMLStringWriter.prototype.closeNode = function (node, level) {
            level || (level = 0);
            switch (false) {
                case !(node instanceof XMLElement):
                    return this.space(level) + '</' + node.name + '>' + this.newline;
                case !(node instanceof XMLDocType):
                    return this.space(level) + ']>' + this.newline;
            }
        };

        return XMLStringWriter;

    })(XMLWriterBase);

}).call(this);
