import React, { useState } from 'react'
import set from 'lodash/set.js'
import unset from 'lodash/unset.js'

/*
 * Helper method to handle object updates
 *
 * This is a wrapper around lodash.set() with extra support for unsetting data.
 *
 * @param {object} obj - The object to update
 * @param {array|string} path - The path to the property to update either as an array or string in dot notation
 * @param {mixed} val - The value to set. If the value holds the string 'unset' the property will be removed
 *
 * @return {object} obj - The mutated object
 */
export const objUpdate = (obj = {}, path, val = undefined) => {
  if (val === undefined) {
    if (Array.isArray(path) && Array.isArray(path[0])) {
      for (const [ipath, ival = undefined] of path) {
        if (ival === undefined) unset(obj, ipath)
        else set(obj, ipath, ival)
      }
    } else unset(obj, path)
  } else set(obj, path, val)

  return obj
}

/*
 * This hooks provides an React state update with an
 * update method that allows us to set deeply nested
 * properties.
 */
export const useStateObject = (dflt = {}) => {
  const [obj, setObj] = useState(dflt)

  const replace = (val) => setObj(val)

  const update = (path, val, altObj = false) => {
    const newObj = altObj ? { ...altObj } : { ...obj }
    objUpdate(newObj, path, val)
    setObj(newObj)

    return newObj
  }

  return [obj, update, replace]
}