import {
nodePathToKeys,
nodePathToKeysChildren,
isLeaf,
asList
} from './utils';
/**
* @module update
*/
/**
* Once fully applied, this returns a new tree with the node at `nodePath` set to the return value of `updater`.
* If any keys on `nodePath` do not exist, a new Immutable `Map` will be created at the missing key.
* If the node at `nodePath` doesn't exist, `updater` will be called with the value of `notSetValue`.
*
* Be aware that by updating values on deep nodes that don't yet exist,
* this may cause `Maps` to be created for child `Iterables` where other types of `Iterables` may be used for children elsewhere in the tree.
* This will be addressed in a future release.
*
* This is intended to be used with a `childPath`, but if no `childPath` is provided
* then this is functionally equivalent to Immutable's `updateIn()` method.
*
* @param {NodePath} nodePath A `NodePath` used to uniquely identify the node to update.
* @param {Updater} updater The function to update the node, which is passed the existing node and must return the updated value of the node.
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node.
* @param {*} [notSetValue=null] When there is no node corresponding to `nodePath`, this value is passed into `updater`.
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`.
*/
function deepUpdate(nodePath, updater, childPath=null, notSetValue=null) {
return (tree) => tree.updateIn(nodePathToKeys(nodePath, childPath), notSetValue, updater);
}
/**
* Once fully applied, this returns a new tree with the children of the node at `nodePath` set to the return value of `updater`.
*
* If no `childPath` is used there will be no change if the node at `nodePath` is not `Iterable`.
*
* If no node exists at `nodePath` then an Immutable `Map` will be created at that location.
* If the node at `nodePath` doesn't exist, `updater` will be called with the value of `notSetValue`.
*
* This is intended to be used with a `childPath`, but if no `childPath` is provided
* then this is functionally equivalent to both Immutable's 'updateIn()` method and `deepUpdate()`.
*
* @param {NodePath} nodePath A `NodePath` used to uniquely identify a node whose children will be updated.
* @param {Updater} updater The function to update the node, which is passed the existing node's children and must return the updated value of the node's children.
* @param {ChildPath} [childPath=null] An `Array` or `List` of keys indicating where to find each node's children from within each node.
* @param {*} [notSetValue=null] When there is no node corresponding to `nodePath`, this value is passed into `updater`.
* @return {InputFunction} A partially applied function which accepts a single tree `Iterable`, and returns the modified tree `Iterable`.
*/
function deepUpdateChildren(nodePath, updater, childPath=null, notSetValue=null) {
return (tree) => {
if(asList(childPath).isEmpty() && isLeaf(tree.getIn(nodePath))) {
return tree;
}
return tree.updateIn(nodePathToKeysChildren(nodePath, childPath), notSetValue, updater);
}
}
export {
deepUpdate,
deepUpdateChildren
}