text: 'use strict'
  
  var util = require('./util')
  var ValidationError = require('./validation-error')
  
  function Wrapper (defaultValue, writable, validators, getter, setter, beforeSet, assert) {
    this.validators = validators
  
    this._defaultValue = defaultValue
    this._writable = writable
    this._getter = getter
    this._setter = setter
    this._beforeSet = beforeSet
    this._assert = assert
    this.isInitialized = false
  
    if (!util.isFunction(defaultValue)) {
      this.isInitialized = true
  
      if (!util.isUndefined(defaultValue)) {
        this._value = defaultValue
      }
    }
  }
  Wrapper.prototype._initialize = function (parent) {
    if (this.isInitialized) {
      return
    }
  
    this._setValue(this._defaultValue(parent), parent)
    this.isInitialized = true
  }
  Wrapper.prototype._getErrors = function (model, key, displayName) {
    model = model || this
    key = key || ''
    displayName = displayName || key
  
    var simple = this.validators
    var errors = []
    var value = this._getValue(model)
    var validator, error
  
    for (var i = 0; i < simple.length; i++) {
      validator = simple[i]
      error = validator.call(model, value, displayName)
  
      if (error) {
        errors.push(new ValidationError(model, error, validator, key))
      }
    }
  
    return errors
  }
  Wrapper.prototype._getValue = function (model) {
    return this._getter ? this._getter.call(model) : this._value
  }
  Wrapper.prototype._setValue = function (value, model) {
    if (!this._writable) {
      throw new Error('Value is readonly')
    }
  
    var val
    if (this._setter) {
      this._setter.call(model, value)
      val = this._getValue(model)
    } else {
      val = this._beforeSet ? this._beforeSet(value) : value
    }
  
    if (this._assert) {
      this._assert(val)
    }
  
    // Hook up the parent ref if necessary
    if (val && val.__supermodel && model) {
      if (!val.__parent) {
        val.__parent = model
      }
    }
  
    this._value = val
  }
  
  Object.defineProperties(Wrapper.prototype, {
    value: {
      get: function () {
        return this._getValue()
      },
      set: function (value) {
        this._setValue(value)
      }
    },
    errors: {
      get: function () {
        return this._getErrors()
      }
    }
  })
  module.exports = Wrapper
  