"use strict";module.exports=Namespace;var Type,Service,Enum,ReflectionObject=require("./object");((Namespace.prototype=Object.create(ReflectionObject.prototype)).constructor=Namespace).className="Namespace";var Field=require("./field"),util=require("./util"),OneOf=require("./oneof");function arrayToJSON(e,t){if(e&&e.length){for(var r={},n=0;n<e.length;++n)r[e[n].name]=e[n].toJSON(t);return r}}function Namespace(e,t){ReflectionObject.call(this,e,t),this.nested=void 0,this._nestedArray=null}function clearCache(e){return e._nestedArray=null,e}Namespace.fromJSON=function(e,t){return new Namespace(e,t.options).addJSON(t.nested)},Namespace.arrayToJSON=arrayToJSON,Namespace.isReservedId=function(e,t){if(e){for(var r=0;r<e.length;++r)if("string"!=typeof e[r]&&e[r][0]<=t&&e[r][1]>t)return!0}return!1},Namespace.isReservedName=function(e,t){if(e){for(var r=0;r<e.length;++r)if(e[r]===t)return!0}return!1},Object.defineProperty(Namespace.prototype,"nestedArray",{get:function(){return this._nestedArray||(this._nestedArray=util.toArray(this.nested))}}),Namespace.prototype.toJSON=function(e){return util.toObject(["options",this.options,"nested",arrayToJSON(this.nestedArray,e)])},Namespace.prototype.addJSON=function(e){if(e)for(var t,r=Object.keys(e),n=0;n<r.length;++n)t=e[r[n]],this.add((void 0!==t.fields?Type.fromJSON:void 0!==t.values?Enum.fromJSON:void 0!==t.methods?Service.fromJSON:void 0!==t.id?Field.fromJSON:Namespace.fromJSON)(r[n],t));return this},Namespace.prototype.get=function(e){return util.getProp(this.nested,e)||null},Namespace.prototype.getEnum=function(e){if(this.nested&&this.nested[e]instanceof Enum)return this.nested[e].values;throw Error("no such enum: "+e)},Namespace.prototype.add=function(e){if(!(e instanceof Field&&void 0!==e.extend||e instanceof Type||e instanceof OneOf||e instanceof Enum||e instanceof Service||e instanceof Namespace))throw TypeError("object must be a valid nested object");if(this.nested){var t=this.get(e.name);if(t)if(t instanceof Namespace&&e instanceof Namespace&&!(t instanceof Type||t instanceof Service)){for(var r=t.nestedArray,n=0;n<r.length;++n)e.add(r[n]);this.remove(t),this.nested||(this.nested={}),e.setOptions(t.options,!0)}else throw Error("duplicate name '"+e.name+"' in "+this)}else this.nested={};return this.nested[e.name]=e,e.onAdd(this),clearCache(this)},Namespace.prototype.remove=function(e){if(!(e instanceof ReflectionObject))throw TypeError("object must be a ReflectionObject");if(e.parent!==this)throw Error(e+" is not a member of "+this);return delete this.nested[e.name],Object.keys(this.nested).length||(this.nested=void 0),e.onRemove(this),clearCache(this)},Namespace.prototype.define=function(e,t){if(util.isString(e))e=e.split(".");else if(!Array.isArray(e))throw TypeError("illegal path");if(e&&e.length&&""===e[0])throw Error("path must be relative");for(var r=this;e.length>0;){var n=e.shift();if(r.nested&&r.nested[n]){if(!((r=r.nested[n])instanceof Namespace))throw Error("path conflicts with non-namespace objects")}else r.add(r=new Namespace(n))}return t&&r.addJSON(t),r},Namespace.prototype.resolveAll=function(){for(var e=this.nestedArray,t=0;t<e.length;)e[t]instanceof Namespace?e[t++].resolveAll():e[t++].resolve();return this.resolve()},Namespace.prototype.lookup=function(e,t,r){if("boolean"==typeof t?(r=t,t=void 0):t&&!Array.isArray(t)&&(t=[t]),util.isString(e)&&e.length){if("."===e)return this.root;e=e.split(".")}else if(!e.length)return this;if(""===e[0])return this.root.lookup(e.slice(1),t);var n=this.get(e[0]);if(n){if(1===e.length){if(!t||t.indexOf(n.constructor)>-1)return n}else if(n instanceof Namespace&&(n=n.lookup(e.slice(1),t,!0)))return n}else for(var o=0;o<this.nestedArray.length;++o)if(this._nestedArray[o]instanceof Namespace&&(n=this._nestedArray[o].lookup(e,t,!0)))return n;return null===this.parent||r?null:this.parent.lookup(e,t)},Namespace.prototype.lookupType=function(e){var t=this.lookup(e,[Type]);if(!t)throw Error("no such type: "+e);return t},Namespace.prototype.lookupEnum=function(e){var t=this.lookup(e,[Enum]);if(!t)throw Error("no such Enum '"+e+"' in "+this);return t},Namespace.prototype.lookupTypeOrEnum=function(e){var t=this.lookup(e,[Type,Enum]);if(!t)throw Error("no such Type or Enum '"+e+"' in "+this);return t},Namespace.prototype.lookupService=function(e){var t=this.lookup(e,[Service]);if(!t)throw Error("no such Service '"+e+"' in "+this);return t},Namespace._configure=function(e,t,r){Type=e,Service=t,Enum=r};