import{format,complementError,asyncMap,warning,deepMerge}from"./util.js";import validators from"./validator/index.js";import{messages as defaultMessages,newMessages}from"./messages.js";function Schema(e){this.rules=null,this._messages=defaultMessages,this.define(e)}Schema.prototype={messages(e){return e&&(this._messages=deepMerge(newMessages(),e)),this._messages},define(e){if(!e)throw new Error("Cannot configure a schema with no rules");if("object"!=typeof e||Array.isArray(e))throw new Error("Rules must be an object");let t,s;for(t in this.rules={},e)e.hasOwnProperty(t)&&(s=e[t],this.rules[t]=Array.isArray(s)?s:[s])},validate(e,t={},s){let r,a,o=e,i=t,n=s;if("function"==typeof i&&(n=i,i={}),!this.rules||0===Object.keys(this.rules).length)return void(n&&n());if(i.messages){let e=this.messages();e===defaultMessages&&(e=newMessages()),deepMerge(e,i.messages),i.messages=e}else i.messages=this.messages();const l={};(i.keys||Object.keys(this.rules)).forEach(t=>{r=this.rules[t],a=o[t],r.forEach(s=>{let r=s;"function"==typeof r.transform&&(o===e&&(o={...o}),a=o[t]=r.transform(a)),r="function"==typeof r?{validator:r}:{...r},r.validator=this.getValidationMethod(r),r.field=t,r.fullField=r.fullField||t,r.type=this.getType(r),r.validator&&(l[t]=l[t]||[],l[t].push({rule:r,value:a,source:o,field:t}))})});const f={};asyncMap(l,i,(e,t)=>{const s=e.rule;let r=!("object"!==s.type&&"array"!==s.type||"object"!=typeof s.fields&&"object"!=typeof s.defaultField);function a(e,t){return{...t,fullField:`${s.fullField}.${e}`}}function o(o=[]){let n=o;if(Array.isArray(n)||(n=[n]),n.length&&warning("async-validator:",n),n.length&&s.message&&(n=[].concat(s.message)),n=n.map(complementError(s)),i.first&&n.length)return f[s.field]=1,t(n);if(r){if(s.required&&!e.value)return n=s.message?[].concat(s.message).map(complementError(s)):i.error?[i.error(s,format(i.messages.required,s.field))]:[],t(n);let r={};if(s.defaultField)for(const t in e.value)e.value.hasOwnProperty(t)&&(r[t]=s.defaultField);r={...r,...e.rule.fields};for(const e in r)if(r.hasOwnProperty(e)){const t=Array.isArray(r[e])?r[e]:[r[e]];r[e]=t.map(a.bind(null,e))}const o=new Schema(r);o.messages(i.messages),e.rule.options&&(e.rule.options.messages=i.messages,e.rule.options.error=i.error),o.validate(e.value,e.rule.options||i,e=>{t(e&&e.length?n.concat(e):e)})}else t(n)}r=r&&(s.required||!s.required&&e.value),s.field=e.field;const n=s.validator(s,e.value,o,e.source,i);n&&n.then&&n.then(()=>o(),e=>o(e))},e=>{!function(e){let t,s,r=[],a={};for(t=0;t<e.length;t++)o=e[t],Array.isArray(o)?r=r.concat.apply(r,o):r.push(o);var o;if(r.length)for(t=0;t<r.length;t++)s=r[t].field,a[s]=a[s]||[],a[s].push(r[t]);else r=null,a=null;n(r,a)}(e)})},getType(e){if(void 0===e.type&&e.pattern instanceof RegExp&&(e.type="pattern"),"function"!=typeof e.validator&&e.type&&!validators.hasOwnProperty(e.type))throw new Error(format("Unknown rule type %s",e.type));return e.type||"string"},getValidationMethod(e){if("function"==typeof e.validator)return e.validator;const t=Object.keys(e),s=t.indexOf("message");return-1!==s&&t.splice(s,1),1===t.length&&"required"===t[0]?validators.required:validators[this.getType(e)]||!1}},Schema.register=function(e,t){if("function"!=typeof t)throw new Error("Cannot register a validator by type, validator is not a function");validators[e]=t},Schema.messages=defaultMessages;export default Schema;