/**
 * Performs a depth first traversal of the character tree, summing the container
 * and inventory contents on the way up the tree
 */
export default function linkInventory(forest, dependencyGraph) {
  // The stack of properties to still navigate
  const stack = [...forest];
  // The current containers we are inside of
  const containerStack = [];

  while (stack.length) {
    const top = stack[stack.length - 1];
    const prop = top.node;
    if (prop._computationDetails.inventoryChildrenVisited) {
      if (prop.type === 'container') containerStack.pop();
      stack.pop();
      handleProp(prop, containerStack, dependencyGraph);
    } else {
      // Add all containers to the stack when we first visit them
      if (prop.type === 'container') {
        containerStack.push(top.node);
      }
      // Push children onto the stack and mark this as children are visited
      stack.push(...top.children);
      prop._computationDetails.inventoryChildrenVisited = true;
    }
  }
}

function handleProp(prop, containerStack, dependencyGraph) {
  // Skip props that aren't part of the inventory
  if (prop.type !== 'item' && prop.type !== 'container') return;
  // Determine if this property is carried, items are carried by default
  let carried = prop.type === 'container' ? prop.carried : true;

  // Item-specific links
  if (prop.type === 'item') {
    if (prop.attuned) {
      dependencyGraph.addLink('itemsAttuned', prop._id, 'attunedItem');
    }
    if (prop.equipped) {
      dependencyGraph.addLink('weightEquipment', prop._id, 'equippedItem');
      dependencyGraph.addLink('valueEquipment', prop._id, 'equippedItem');
    }
  }

  // Get the parent container
  const container = containerStack[containerStack.length - 1];

  if (container) {
    // The container depends on this prop for its contents data
    dependencyGraph.addLink(container._id, prop._id, 'containerContents');
  } else {
    // There is no parent container, the character totals depend on this prop
    dependencyGraph.addLink('weightTotal', prop._id, 'inventoryStats');
    dependencyGraph.addLink('valueTotal', prop._id, 'inventoryStats');
    if (carried) {
      dependencyGraph.addLink('weightCarried', prop._id, 'inventoryStats');
      dependencyGraph.addLink('valueCarried', prop._id, 'inventoryStats');
    }
  }
}
