import {isObservable,isObservableProp,observe} from 'mobx'
import camelCase from './camelCase'

import Validator from '../Common-Library/Validator'

export const prefix = "validateError"


export function modelWrapper(target)
{
    
    //开启监听
    target.prototype.openMonitor = function(){
        initPropotype(this)
        this.__beginVali__ = true
        for(let key in this)
        {
            if(!isObservableProp(this,key))
                continue
            //创建监听
            createListener(this,key)
        }
    }

    //关闭监听
    target.prototype.stopMonitor = function(){
        this.__beginVali__ = false
        if(this.__dispose__ && this.__dispose__.length)
        {
            for(let dispose of this.__dispose__)
            {
                dispose()
            }
            this.__dispose__.splice(0,this.__dispose__.length)
        }
    }

    //返回快照记录
    target.prototype.getDisplay = function(){
        return {
            model :{...this},
            changes:[...this.__displays__]
        }
    }

    target.prototype.attachErrors = attachErrors

    target.prototype.isValid = function(){
        return !this.getValidateError()
    }
    target.prototype.getValidateError = function(){
        for(let key of this.__validateFields__.keys)
        {
            let msg = this[camelCase(prefix,key)]
            if(msg)
                return msg
        }
    }
    target.prototype.loadDisplay=function(model,changes){
        initPropotype(this)
        changes.forEach(val=>this.__displays__.add(val))
        this.__beginVali__=false
        this.inDisplay=true
        Object.assign(this,model)
    }

    target.prototype.displayChanged=function(key){
        return this.__displays__.has(key)
    }

}

function createListener(_this,field)
{
    
    if(_this.descriptor[field])   //添加校验值记录
        _this.__validateFields__.add(field)

    let dispose = observe(_this,field,change=>{
        _this.__displays__.add(field)
        if(!_this.descriptor[field])
        {
            console.warn(`${field}字段缺少校验`)
            return 
        }
        //开始校验
        Validator.validate(_this,{[field]:_this.descriptor[field]},(errors, fields)=>{
            //校验单个字段完毕
            if(!errors) //无错，需清空
            {
                _this.attachErrors([{message:"",field}])
            }
        }) 
    })
    _this.__dispose__.push(dispose)
}

function attachErrors(errors)
{
    if(!errors)
        return 
    for(let e of errors)
    {
        let key = camelCase(prefix,e.field)
        
        this.__errors__[key] = e.message
    }
}
function  clearErrors(){

}

function initPropotype(target)
{
    let _this = target

    if(!_this.hasOwnProperty("__beginVali__"))
    {
        _this.__beginVali__=false
    }

    if(!_this.hasOwnProperty("__errors__"))
    {
        Object.defineProperty(_this, '__errors__', {
            configurable: true,
            enumerable: false,
            value: {},
        })
    }

    if(!_this.hasOwnProperty("__dispose__"))
    {
        Object.defineProperty(_this, '__dispose__', {
            configurable: true,
            enumerable: false,
            value: [],
        })
    }

    if(!_this.hasOwnProperty("__displays__"))
    {
        Object.defineProperty(_this, '__displays__', {
            configurable: true,
            enumerable: false,
            value: new Set(),
        })
    }

    if(!_this.hasOwnProperty("__validateFields__"))
    {
        Object.defineProperty(_this, '__validateFields__', {
            configurable: true,
            enumerable: false,
            value: new Set(),
        })
        
    }
}
