requireInjector(getfenv(1))

local Point = require('point')
local Util  = require('util')

local checkedNodes = { }
local nodes = { }
local box = { x = 65, ex = 69, y = 65, ey = 70, z = -23, ez = -19 }

local function inBox(pt, box)
  return pt.x >= box.x and
         pt.y >= box.y and
         pt.z >= box.z and
         pt.x <= box.ex and
         pt.y <= box.ey and
         pt.z <= box.ez
end

local function toKey(pt)
  return table.concat({ pt.x, pt.y, pt.z }, ':')
end

local function addNode(node)

  for i = 0, 5 do
    local hi = turtle.getHeadingInfo(i)
    local testNode = { x = node.x + hi.xd, y = node.y + hi.yd, z = node.z + hi.zd }

    if inBox(testNode, box) then
      local key = toKey(testNode)
      if not checkedNodes[key] then
        nodes[key] = testNode
      end
    end
  end
end

local function dig(facing)
  local direction = facing
  if direction == 'forward' then
    direction = turtle.getHeadingInfo(turtle.point.heading).direction
  end
  local hi = turtle.getHeadingInfo(direction)
  local node = { x = turtle.point.x + hi.xd, y = turtle.point.y + hi.yd, z = turtle.point.z + hi.zd }
  if inBox(node, box) then
    if turtle.getAction(facing).dig() then
      addNode(node)
    end
  end
end

local function level()
  repeat
    local node = { x = turtle.point.x, y = turtle.point.y, z = turtle.point.z }
    local key = toKey(node)

    checkedNodes[key] = true
    nodes[key] = nil

    dig('down')
    dig('up')
    dig('forward')

    print(string.format('%d nodes remaining', Util.size(nodes)))

    if Util.size(nodes) == 0 then
      break
    end

    local node = Point.closest(turtle.point, nodes)
    if not turtle.gotoPoint(node) then
      break
    end
  until turtle.abort
end

local pt = Util.shallowCopy(turtle.point)
turtle.setPolicy(turtle.policies.none)
if turtle.pathfind({ x = 65, y = 70, z = -23 }) then
--turtle.reset()
  turtle.setPolicy(turtle.policies.digOnly)
  level()
end
turtle.pathfind(pt)
--local s, m = turtle.run(level)
