var util = this

return util

util.dainty_assign = function (target, source) {
  Object.keys(source).forEach(function (k) {
    if (typeof source[k] == "function") return
    if (!(k in target)) return
    if (Array.isArray(source[k])) target[k] = deep_copy(source[k])
    else if (Object.isObject(source[k])) Object.dainty_assign(target[k], source[k])
    else target[k] = source[k]
  })
}

util.get = function (obj, path, defValue) {
  if (!path) return null
  var pathArray = Array.isArray(path) ? path : path.match(/([^[.\]])+/g)
  var result = pathArray.reduce((prevObj, key) => prevObj && prevObj[key], obj)
  return result == null ? defValue : result
}

util.isEmpty = function(o) {
  return Object.keys(o).length == 0
}

util.dig = function (obj, path, deflt = {}) {
  var pp = path.split(".")
  for (var i = 0; i < pp.length - 1; i++) {
    obj = obj[pp[i]] = obj[pp[i]] || {}
  }
  obj[pp[pp.length - 1]] = deflt
  return deflt
}

util.access = function (obj, name) {
  var dig = name.split(".")
  for (var i of dig) {
    obj = obj[i]
    if (!obj) return null
  }
  return obj
}

util.mergekey = function (o1, o2, k) {
  if (!o2) return
  if (typeof o2[k] == "object") {
    if (Array.isArray(o2[k])) o1[k] = deep_copy(o2[k])
    else {
      if (!o1[k]) o1[k] = {}
      if (typeof o1[k] == "object") util.merge(o1[k], o2[k])
      else o1[k] = o2[k]
    }
  } else o1[k] = o2[k]
}

util.merge = function (target, ...objs) {
  for (var obj of objs) for (var key of Object.keys(obj)) util.mergekey(target, obj, key)
  return target
}

util.copy = function (proto, ...objs) {
  var c = Object.create(proto)
  for (var obj of objs) Object.mixin(c, obj)
  return c
}

util.obj_lerp = function(a,b,t) {
  if (a.lerp) return a.lerp(b, t)
  var obj = {}
  Object.keys(a).forEach(function (key) {
    obj[key] = a[key].lerp(b[key], t)
  })
  return obj
}

util.normalizeSpacing = function normalizeSpacing(spacing) {
  if (typeof spacing == 'number') {
    return {l: spacing, r: spacing, t: spacing, b: spacing}
  } else if (Array.isArray(spacing)) {
    if (spacing.length == 2) {
      return {l: spacing[0], r: spacing[0], t: spacing[1], b: spacing[1]}
    } else if (spacing.length == 4) {
      return {l: spacing[0], r: spacing[1], t: spacing[2], b: spacing[3]}
    }
  } else if (typeof spacing == 'object') {
    return {l: spacing.l || 0, r: spacing.r || 0, t: spacing.t || 0, b: spacing.b || 0}
  } else {
    return {l:0, r:0, t:0, b:0}
  }
}

function deep_copy(from) {
  return json.decode(json.encode(from))
}

return util
