
import {computed,observe} from 'mobx'
import Validator from './Validator'

function defineComputedProperty(target, name, descriptor){
  Object.defineProperty(
    target,
    name,
    descriptor
  );
  computed(target, name, descriptor);
}
export const prefix = "validateError"

export function camelCase(prefix,after)
{
    after = after.substring(0,1).toUpperCase()+after.substring(1);
    return prefix+after
}

export default function validate(target, name, descriptor)
{
    const clazz = target.constructor;

    const prototype = clazz.prototype
    
    const validateName = camelCase('validateError', name);
    
    //添加值拦截函数
    if (!clazz.hasOwnProperty('hasEnV')){
        Object.defineProperty(clazz, 'hasEnV', {
            configurable: true,
            enumerable: false,
            value: false,
        })
    }
    if (!prototype.hasOwnProperty('openValidate')){
        Object.defineProperty(prototype,'openValidate',{
            value:openValidate
        })
    }

    if (!prototype.hasOwnProperty('closeValidate')){
        Object.defineProperty(prototype,'closeValidate',{
            value:closeValidate
        })
    }
    if (!prototype.hasOwnProperty('attachErrors')){
        Object.defineProperty(prototype,'attachErrors',{
            value:attachErrors
        })
    }

    
    //增加
    if (target.hasOwnProperty('__validateFields')){
        target.__validateFields.push(name);
      } else {
        Object.defineProperty(target, '__validateFields', {
          configurable: true,
          enumerable: false,
          value: [name],
        })
        Object.defineProperty(target, '__dispose', {
            configurable: true,
            enumerable: false,
            value: [],
          })
    }
    //校验错误
    if (!target.hasOwnProperty('validateError')) {
        defineComputedProperty(target, 'validateError', {
          configurable: true,
          enumerable: false,
          get: getValidateError,
        })
      }
    //返回是否有错误
    if (!target.hasOwnProperty('isValid')) {
        defineComputedProperty(target, 'isValid', {
          configurable: true,
          enumerable: false,
          get: getIsValid,
        })
      }
    
}

function getValidateError() {
    return this.__validateFields.find(key =>this[camelCase(prefix,key)]);
}

function getIsValid() {
    return !this.validateError;
}


function openValidate()
{
    if(this.hasEnV==true)
            return 
    let descriptor = this.descriptor
    for(let field of this.__validateFields)
    {
       if(!descriptor[field])
       {    
            console.warn(`${field}字段缺少校验`)
            continue
       }
        let dispose= observe(this,field,(change)=>{
            //单个字段校验，发起校验
            Validator.validate(this,{[field]:descriptor[field]},(errors, fields)=>{
                //校验单个字段完毕
                if(!errors) //无错，需清空
                {
                    let key = camelCase(prefix,field)
                    this[key] = "" 
                }
            }) 
       })
       this.__dispose.push(dispose)
    }
    this.hasEnV=true
}

function closeValidate()
{
    if(this.hasEnV){
        this.hasEnV=false
        for(let dispose of this.__dispose)
        {
            dispose() //关闭影响
        }
        this.__dispose=[] //清空
    }
}
function attachErrors(errors)
{
    if(!errors)
        return 
    for(let e of errors)
    {
        let key = camelCase(prefix,e.field)
        if(!this.hasOwnProperty(key))
        {
            Object.defineProperty(this, key, {
                configurable: true,
                enumerable: false,
                value: e.message,
              })
        }
        else
            this[key] = e.message
    }
}