export const NODE_KEY = '$treeNodeId'

export const markNodeData = function(node, data) {
  if (!data || data[NODE_KEY]) return
  Object.defineProperty(data, NODE_KEY, {
    value: node.id,
    enumerable: false,
    configurable: false,
    writable: false
  })
}

export const getNodeKey = function(key, data) {
  if (!key) return data[NODE_KEY]
  return data[key]
}

export const objectAssign = function(target) {
  for (let i = 1, j = arguments.length; i < j; i++) {
    const source = arguments[i] || {}
    for (const prop in source) {
      if (source.hasOwnProperty(prop)) {
        const value = source[prop]
        if (value !== undefined) {
          target[prop] = value
        }
      }
    }
  }

  return target
}

// TODO: use native Array.find, Array.findIndex when IE support is dropped
export const arrayFindIndex = function(arr, pred) {
  for (let i = 0; i !== arr.length; ++i) {
    if (pred(arr[i])) {
      return i
    }
  }
  return -1
}

export const getChildState = function(node) {
  let all = true
  let none = true
  let allWithoutDisable = true
  for (let i = 0, j = node.length; i < j; i++) {
    const n = node[i]
    if (n.checked !== true || n.indeterminate) {
      all = false
      if (!n.disabled) {
        allWithoutDisable = false
      }
    }
    if (n.checked !== false || n.indeterminate) {
      none = false
    }
  }

  return {
    all,
    none,
    allWithoutDisable,
    half: !all && !none
  }
}

export const reInitChecked = function(node) {
  if (!node || node.childNodesId.length === 0) return

  const childNodes = node.getChildNodes(node.childNodesId)
  const {
    all,
    none,
    half
  } = getChildState(childNodes)
  if (all) {
    node.checked = true
    node.indeterminate = false
  } else if (half) {
    node.checked = false
    node.indeterminate = true
  } else if (none) {
    node.checked = false
    node.indeterminate = false
  }

  const parent = node.getParent(node.parentId)
  if (!parent || parent.level === 0) return

  if (!node.store().checkStrictly) {
    reInitChecked(parent)
  }
}

export const getPropertyFromData = function(node, prop) {
  const props = node.store().props
  const data = node.data || {}
  const config = props[prop]

  if (typeof config === 'function') {
    return config(data, node)
  } else if (typeof config === 'string') {
    return data[config]
  } else if (typeof config === 'undefined') {
    const dataProp = data[prop]
    return dataProp === undefined ? '' : dataProp
  }
}
