'use strict';

var _commonjsHelpers = require('../../../_virtual/_commonjsHelpers.js');
var parser = require('../../../_virtual/parser2.js');
var sax = require('../../sax/lib/sax.js');
var EventEmitter = require('events');
var bom = require('./bom.js');
var processors = require('./processors.js');
var require$$4 = require('timers');
var defaults = require('./defaults.js');

var hasRequiredParser;

function requireParser () {
	if (hasRequiredParser) return parser.__exports;
	hasRequiredParser = 1;
	(function (exports) {
		// Generated by CoffeeScript 1.12.7
		(function() {
		  var bom$1, defaults$1, events, isEmpty, processItem, processors$1, sax$1, setImmediate,
		    bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
		    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;

		  sax$1 = sax.__require();

		  events = EventEmitter;

		  bom$1 = bom.__require();

		  processors$1 = processors.__require();

		  setImmediate = require$$4.setImmediate;

		  defaults$1 = defaults.__require().defaults;

		  isEmpty = function(thing) {
		    return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
		  };

		  processItem = function(processors, item, key) {
		    var i, len, process;
		    for (i = 0, len = processors.length; i < len; i++) {
		      process = processors[i];
		      item = process(item, key);
		    }
		    return item;
		  };

		  exports.Parser = (function(superClass) {
		    extend(Parser, superClass);

		    function Parser(opts) {
		      this.parseStringPromise = bind(this.parseStringPromise, this);
		      this.parseString = bind(this.parseString, this);
		      this.reset = bind(this.reset, this);
		      this.assignOrPush = bind(this.assignOrPush, this);
		      this.processAsync = bind(this.processAsync, this);
		      var key, ref, value;
		      if (!(this instanceof exports.Parser)) {
		        return new exports.Parser(opts);
		      }
		      this.options = {};
		      ref = defaults$1["0.2"];
		      for (key in ref) {
		        if (!hasProp.call(ref, key)) continue;
		        value = ref[key];
		        this.options[key] = value;
		      }
		      for (key in opts) {
		        if (!hasProp.call(opts, key)) continue;
		        value = opts[key];
		        this.options[key] = value;
		      }
		      if (this.options.xmlns) {
		        this.options.xmlnskey = this.options.attrkey + "ns";
		      }
		      if (this.options.normalizeTags) {
		        if (!this.options.tagNameProcessors) {
		          this.options.tagNameProcessors = [];
		        }
		        this.options.tagNameProcessors.unshift(processors$1.normalize);
		      }
		      this.reset();
		    }

		    Parser.prototype.processAsync = function() {
		      var chunk, err;
		      try {
		        if (this.remaining.length <= this.options.chunkSize) {
		          chunk = this.remaining;
		          this.remaining = '';
		          this.saxParser = this.saxParser.write(chunk);
		          return this.saxParser.close();
		        } else {
		          chunk = this.remaining.substr(0, this.options.chunkSize);
		          this.remaining = this.remaining.substr(this.options.chunkSize, this.remaining.length);
		          this.saxParser = this.saxParser.write(chunk);
		          return setImmediate(this.processAsync);
		        }
		      } catch (error1) {
		        err = error1;
		        if (!this.saxParser.errThrown) {
		          this.saxParser.errThrown = true;
		          return this.emit(err);
		        }
		      }
		    };

		    Parser.prototype.assignOrPush = function(obj, key, newValue) {
		      if (!(key in obj)) {
		        if (!this.options.explicitArray) {
		          return obj[key] = newValue;
		        } else {
		          return obj[key] = [newValue];
		        }
		      } else {
		        if (!(obj[key] instanceof Array)) {
		          obj[key] = [obj[key]];
		        }
		        return obj[key].push(newValue);
		      }
		    };

		    Parser.prototype.reset = function() {
		      var attrkey, charkey, ontext, stack;
		      this.removeAllListeners();
		      this.saxParser = sax$1.parser(this.options.strict, {
		        trim: false,
		        normalize: false,
		        xmlns: this.options.xmlns
		      });
		      this.saxParser.errThrown = false;
		      this.saxParser.onerror = (function(_this) {
		        return function(error) {
		          _this.saxParser.resume();
		          if (!_this.saxParser.errThrown) {
		            _this.saxParser.errThrown = true;
		            return _this.emit("error", error);
		          }
		        };
		      })(this);
		      this.saxParser.onend = (function(_this) {
		        return function() {
		          if (!_this.saxParser.ended) {
		            _this.saxParser.ended = true;
		            return _this.emit("end", _this.resultObject);
		          }
		        };
		      })(this);
		      this.saxParser.ended = false;
		      this.EXPLICIT_CHARKEY = this.options.explicitCharkey;
		      this.resultObject = null;
		      stack = [];
		      attrkey = this.options.attrkey;
		      charkey = this.options.charkey;
		      this.saxParser.onopentag = (function(_this) {
		        return function(node) {
		          var key, newValue, obj, processedKey, ref;
		          obj = Object.create(null);
		          obj[charkey] = "";
		          if (!_this.options.ignoreAttrs) {
		            ref = node.attributes;
		            for (key in ref) {
		              if (!hasProp.call(ref, key)) continue;
		              if (!(attrkey in obj) && !_this.options.mergeAttrs) {
		                obj[attrkey] = Object.create(null);
		              }
		              newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key];
		              processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key;
		              if (_this.options.mergeAttrs) {
		                _this.assignOrPush(obj, processedKey, newValue);
		              } else {
		                obj[attrkey][processedKey] = newValue;
		              }
		            }
		          }
		          obj["#name"] = _this.options.tagNameProcessors ? processItem(_this.options.tagNameProcessors, node.name) : node.name;
		          if (_this.options.xmlns) {
		            obj[_this.options.xmlnskey] = {
		              uri: node.uri,
		              local: node.local
		            };
		          }
		          return stack.push(obj);
		        };
		      })(this);
		      this.saxParser.onclosetag = (function(_this) {
		        return function() {
		          var cdata, emptyStr, key, node, nodeName, obj, objClone, old, s, xpath;
		          obj = stack.pop();
		          nodeName = obj["#name"];
		          if (!_this.options.explicitChildren || !_this.options.preserveChildrenOrder) {
		            delete obj["#name"];
		          }
		          if (obj.cdata === true) {
		            cdata = obj.cdata;
		            delete obj.cdata;
		          }
		          s = stack[stack.length - 1];
		          if (obj[charkey].match(/^\s*$/) && !cdata) {
		            emptyStr = obj[charkey];
		            delete obj[charkey];
		          } else {
		            if (_this.options.trim) {
		              obj[charkey] = obj[charkey].trim();
		            }
		            if (_this.options.normalize) {
		              obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim();
		            }
		            obj[charkey] = _this.options.valueProcessors ? processItem(_this.options.valueProcessors, obj[charkey], nodeName) : obj[charkey];
		            if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
		              obj = obj[charkey];
		            }
		          }
		          if (isEmpty(obj)) {
		            if (typeof _this.options.emptyTag === 'function') {
		              obj = _this.options.emptyTag();
		            } else {
		              obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr;
		            }
		          }
		          if (_this.options.validator != null) {
		            xpath = "/" + ((function() {
		              var i, len, results;
		              results = [];
		              for (i = 0, len = stack.length; i < len; i++) {
		                node = stack[i];
		                results.push(node["#name"]);
		              }
		              return results;
		            })()).concat(nodeName).join("/");
		            (function() {
		              var err;
		              try {
		                return obj = _this.options.validator(xpath, s && s[nodeName], obj);
		              } catch (error1) {
		                err = error1;
		                return _this.emit("error", err);
		              }
		            })();
		          }
		          if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') {
		            if (!_this.options.preserveChildrenOrder) {
		              node = Object.create(null);
		              if (_this.options.attrkey in obj) {
		                node[_this.options.attrkey] = obj[_this.options.attrkey];
		                delete obj[_this.options.attrkey];
		              }
		              if (!_this.options.charsAsChildren && _this.options.charkey in obj) {
		                node[_this.options.charkey] = obj[_this.options.charkey];
		                delete obj[_this.options.charkey];
		              }
		              if (Object.getOwnPropertyNames(obj).length > 0) {
		                node[_this.options.childkey] = obj;
		              }
		              obj = node;
		            } else if (s) {
		              s[_this.options.childkey] = s[_this.options.childkey] || [];
		              objClone = Object.create(null);
		              for (key in obj) {
		                if (!hasProp.call(obj, key)) continue;
		                objClone[key] = obj[key];
		              }
		              s[_this.options.childkey].push(objClone);
		              delete obj["#name"];
		              if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
		                obj = obj[charkey];
		              }
		            }
		          }
		          if (stack.length > 0) {
		            return _this.assignOrPush(s, nodeName, obj);
		          } else {
		            if (_this.options.explicitRoot) {
		              old = obj;
		              obj = Object.create(null);
		              obj[nodeName] = old;
		            }
		            _this.resultObject = obj;
		            _this.saxParser.ended = true;
		            return _this.emit("end", _this.resultObject);
		          }
		        };
		      })(this);
		      ontext = (function(_this) {
		        return function(text) {
		          var charChild, s;
		          s = stack[stack.length - 1];
		          if (s) {
		            s[charkey] += text;
		            if (_this.options.explicitChildren && _this.options.preserveChildrenOrder && _this.options.charsAsChildren && (_this.options.includeWhiteChars || text.replace(/\\n/g, '').trim() !== '')) {
		              s[_this.options.childkey] = s[_this.options.childkey] || [];
		              charChild = {
		                '#name': '__text__'
		              };
		              charChild[charkey] = text;
		              if (_this.options.normalize) {
		                charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim();
		              }
		              s[_this.options.childkey].push(charChild);
		            }
		            return s;
		          }
		        };
		      })(this);
		      this.saxParser.ontext = ontext;
		      return this.saxParser.oncdata = (function(_this) {
		        return function(text) {
		          var s;
		          s = ontext(text);
		          if (s) {
		            return s.cdata = true;
		          }
		        };
		      })();
		    };

		    Parser.prototype.parseString = function(str, cb) {
		      var err;
		      if ((cb != null) && typeof cb === "function") {
		        this.on("end", function(result) {
		          this.reset();
		          return cb(null, result);
		        });
		        this.on("error", function(err) {
		          this.reset();
		          return cb(err);
		        });
		      }
		      try {
		        str = str.toString();
		        if (str.trim() === '') {
		          this.emit("end", null);
		          return true;
		        }
		        str = bom$1.stripBOM(str);
		        if (this.options.async) {
		          this.remaining = str;
		          setImmediate(this.processAsync);
		          return this.saxParser;
		        }
		        return this.saxParser.write(str).close();
		      } catch (error1) {
		        err = error1;
		        if (!(this.saxParser.errThrown || this.saxParser.ended)) {
		          this.emit('error', err);
		          return this.saxParser.errThrown = true;
		        } else if (this.saxParser.ended) {
		          throw err;
		        }
		      }
		    };

		    Parser.prototype.parseStringPromise = function(str) {
		      return new Promise((function(_this) {
		        return function(resolve, reject) {
		          return _this.parseString(str, function(err, value) {
		            if (err) {
		              return reject(err);
		            } else {
		              return resolve(value);
		            }
		          });
		        };
		      })(this));
		    };

		    return Parser;

		  })(events);

		  exports.parseString = function(str, a, b) {
		    var cb, options, parser;
		    if (b != null) {
		      if (typeof b === 'function') {
		        cb = b;
		      }
		      if (typeof a === 'object') {
		        options = a;
		      }
		    } else {
		      if (typeof a === 'function') {
		        cb = a;
		      }
		      options = {};
		    }
		    parser = new exports.Parser(options);
		    return parser.parseString(str, cb);
		  };

		  exports.parseStringPromise = function(str, a) {
		    var options, parser;
		    if (typeof a === 'object') {
		      options = a;
		    }
		    parser = new exports.Parser(options);
		    return parser.parseStringPromise(str);
		  };

		}).call(_commonjsHelpers.commonjsGlobal); 
	} (parser.__exports));
	return parser.__exports;
}

exports.__require = requireParser;
