'use strict';

var helpers = require('./helpers');
var extend = require('extend-object');


var EXCLUDE = {
    constructor: true,
    parent: true,
    prototype: true,
    toJSON: true,
    toString: true,
    xml: true
};


module.exports = function (JXT, opts) {
    function Stanza(data, xml, parent) {
        var self = this;

        var parentNode = (xml || {}).parentNode || (parent || {}).xml;
        var parentNS = (parentNode || {}).namespaceURI;

        self.xml = xml || helpers.createElement(self._NS, self._EL, parentNS);

        Object.keys(opts.prefixes || {}).forEach(function (prefix) {
            var namespace = opts.prefixes[prefix];
            self.xml.setAttribute('xmlns:' + prefix, namespace);
        });

        self._extensions = {};

        for (var i = 0, len = self.xml.childNodes.length; i < len; i++) {
            var child = self.xml.childNodes[i];
            var ChildJXT = JXT.getDefinition(child.localName, child.namespaceURI);
            if (ChildJXT !== undefined) {
                var name = ChildJXT.prototype._name;
                self._extensions[name] = new ChildJXT(null, child);
                self._extensions[name].parent = self;
            }
        }

        extend(self, data);

        if (opts.init) {
            opts.init.apply(self, [data]);
        }

        return self;
    }


    Stanza.prototype._name = opts.name;
    Stanza.prototype._eventname = opts.eventName;
    Stanza.prototype._NS = opts.namespace;
    Stanza.prototype._EL = opts.element || opts.name;
    Stanza.prototype._TAGS = opts.tags || [];

    Stanza.prototype.toString = function () {
        return this.xml.toString();
    };

    Stanza.prototype.toJSON = function () {
        var prop;
        var result = {};

        for (prop in this._extensions) {
            if (this._extensions[prop].toJSON && prop[0] !== '_') {
                result[prop] = this._extensions[prop].toJSON();
            }
        }

        for (prop in this) {
            var allowedName = !EXCLUDE[prop] && prop[0] !== '_';
            var isExtensionName = JXT.getExtensions(this._EL, this._NS)[prop];

            if (allowedName && !isExtensionName) {
                var val = this[prop];
                if (typeof val === 'function') {
                    continue;
                }
                var type = Object.prototype.toString.call(val);
                if (type.indexOf('Object') >= 0) {
                    if (Object.keys(val).length > 0) {
                        result[prop] = val;
                    }
                } else if (type.indexOf('Array') >= 0) {
                    if (val.length > 0) {
                        var vals = [];
                        for (var n in val) {
                            var nval = val[n];
                            if (nval.toJSON !== undefined) {
                                vals.push(nval.toJSON());
                            } else {
                                vals.push(nval);
                            }
                        }
                        result[prop] = vals;
                    }
                } else if (val !== undefined && val !== false && val !== '') {
                    result[prop] = val;
                }
            }
        }

        return result;
    };

    return Stanza;
};

@@ -559,27 +559,22 @@
 eys(
-opts.prefixes %7C%7C %7B%7D
+self._PREFIXES
 ).fo
@@ -631,21 +631,22 @@
 e = 
-opts.prefixes
+self._PREFIXES
 %5Bpre
@@ -1524,32 +1524,86 @@
 t %7C%7C opts.name;%0A
+    Stanza.prototype._PREFIXES = opts.prefixes %7C%7C %7B%7D;%0A
     Stanza.proto

Save defined prefixes