local function miner_overview(obj)
   local scale = (obj.inv/25) * 3
   local formspec =
   kobo.unit_inv..
   'textarea[3.25,0;7.5,1;;;Miner]'..
   'image[0,0;3,3;kobo_miner_snap.png]'..
   'textarea[3.25,.75;7.5,2.25;;;Miner state: '..obj.state..'.\n'..
   'Miner inventory: '..obj.inv..' '..obj.mat..'.]'..
   'image[0,4.5;'..scale..',.25;kobo_inv_fg.png]'
   return formspec
end

core.register_entity('kobo:miner', {
   initial_properties = {
      visual = 'mesh',
      mesh = 'kobo_worker.obj',
      visual_size = {x=10, y=10},
      physical = true,
      collide_with_objects = false,
      collisionbox = {-.125, -.5, -.125, .125, 0, .125},
      textures = {'kobo_miner.png'},
      automatic_face_movement_dir = 0.0,
   },

   on_activate = function(self, staticdata, dtime_s)
      local data = core.deserialize(staticdata)
      if data then
         self.node_timer = data.node_timer
         self.owner = data.owner
         self.home = data.home
         self.state = data.state
         self.path = data.path
         self.step = data.step
         self.inv = data.inv
         self.last_job = data.last_job
         self.mat = data.mat
      end
   end,

   get_staticdata = function(self)
      local data ={}
      data.node_timer = self.node_timer
      data.owner = self.owner
      data.home = self.home
      data.state = self.state
      data.path = self.path
      data.step = self.step
      data.inv = self.inv
      data.last_job = self.last_job
      data.mat = self.mat
      return core.serialize(data)
   end,

   on_step = function(self, dtime, moveresults)
      self.node_timer = (self.node_timer or 0) + dtime
      if self.node_timer > 1 then
         self.node_timer = 0
         if self.state == 'idle' then --Find the lazybones some work.
            local last_job = self.last_job
            if not last_job then
               local self_pos = self.object:get_pos()
               local name = self.owner
               local resources = kobo.resources[name]
               local metal = resources.last_metal
               local stone = resources.last_stone
               local stone_mines = core.find_node_near(self_pos, 10, 'group:stone_mine')
               local metal_mines = core.find_node_near(self_pos, 10, 'group:metal_mine')
               if stone_mines then
                  local node = core.get_node(self_pos)
                  local def = core.registered_nodes[node.name]
                  if def.walkable then
                     self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                  end
                  local path = core.find_path(self_pos, vector.add(stone_mines, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  else --Make the unit wander around for a while.
                     self.state = 'idle'
                  end
               elseif metal_mines then
                  local node = core.get_node(self_pos)
                  local def = core.registered_nodes[node.name]
                  if def.walkable then
                     self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                  end
                  local path = core.find_path(self_pos, vector.add(metal_mines, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  else --Make the unit wander around for a while.
                     self.state = 'idle'
                  end
               elseif metal.x then
                  local node = core.get_node(self_pos)
                  local def = core.registered_nodes[node.name]
                  if def.walkable then
                     self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                  end
                  local path = core.find_path(self_pos, vector.add(metal, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  else --Make the unit wander around for a while.
                     self.state = 'idle'
                  end
               elseif stone.x then
                  local node = core.get_node(self_pos)
                  local def = core.registered_nodes[node.name]
                  if def.walkable then
                     self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                  end
                  local path = core.find_path(self_pos, vector.add(stone, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  else --Make the unit wander around for a while.
                     self.state = 'idle'
                  end
               else
                  local buildings = core.find_node_near(self_pos, 10, 'group:storage')
                  if buildings then
                     local node = core.get_node(self_pos)
                     local def = core.registered_nodes[node.name]
                     if def.walkable then
                        self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                     end
                     local path = core.find_path(self_pos, vector.add(buildings, {x=0, y=1, z=0}), 5, 1, 1)
                     if path then
                        self.path = path
                        self.step = 2
                        self.state = 'traveling'
                     end
                  else --Make the unit wander around for a while.
                     self.state = 'idle'
                  end
               end
            else --go back to previous worksite
               local self_pos = self.object:get_pos()
               local node = core.get_node(self_pos)
               local def = core.registered_nodes[node.name]
               if def.walkable then
                  self_pos = vector.add(self_pos, {x=0, y=1, z=0})
               end
               local path = core.find_path(self_pos, vector.add(self.last_job, {x=0, y=1, z=0}), 5, 1, 1)
               if path then
                  self.path = path
                  self.step = 2
                  self.state = 'traveling'
               else
                  self.state = 'idle'
               end
            end
         elseif self.state == 'traveling' then
            if #self.path > (self.step - 1) then
               local pos = self.object:get_pos()
               local perhaps = vector.direction(pos, self.path[self.step])
               self.object:set_velocity({x = perhaps.x, y = 0, z = perhaps.z})
               self.step = self.step + 1
            else
               local self_pos = vector.round(self.object:get_pos())
               local metal = core.find_node_near(self_pos, 1, 'group:metal_mine', true)
               local stone = core.find_node_near(self_pos, 1, 'group:stone_mine', true)
               if metal then
                  self.object:set_velocity({x=0, y=0, z=0})
                  self.state = 'working'
                  self.last_job = metal
                  self.mat = 'metal'
               elseif stone then
                  self.object:set_velocity({x=0, y=0, z=0})
                  self.state = 'working'
                  self.last_job = stone
                  self.mat = 'stone'
               elseif core.find_node_near(self_pos, 1, 'group:storage', true) then
                  local resources = kobo.resources[self.owner]
                  if self.mat == 'metal' then
                     resources.metal = resources.metal + self.inv
                  elseif self.mat == 'stone' then
                     resources.stone = resources.stone + self.inv
                  end
                  self.inv = 0
                  local player = core.get_player_by_name(self.owner)
                  kobo.hud_refresh(player)
                  self.state = 'idle'
               else
                  self.state = 'idle'
               end
            end
         elseif self.state == 'working' then
            local inventory_count = self.inv
            if inventory_count < 25 then
               self.inv = self.inv + 1
               local pos = self.last_job
               local node = core.get_node(pos)
               local meta = core.get_meta(pos)
               local remaining = meta:get_int('remaining')
               if remaining == 0 then
                  local def = minetest.registered_nodes[node.name]
                  remaining = def._initial_count
                  if remaining then
                     meta:set_int('remaining', remaining - 1)
                  end
               elseif remaining == 1 then
                  core.remove_node(pos)
                  self.state = 'idle'
                  self.last_job = nil
               else
                  meta:set_int('remaining', remaining - 1)
               end
            else
               local self_pos = self.object:get_pos()
               local storage_point = core.find_node_near(self_pos, 10, 'group:storage')
               if storage_point then
                  local node = core.get_node(self_pos)
                  local def = core.registered_nodes[node.name]
                  if def.walkable then
                     self_pos = vector.add(self_pos, {x=0, y=1, z=0})
                  end
                  local path = core.find_path(self_pos, vector.add(storage_point, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  end
               else
                  local path = core.find_path(self_pos, vector.add(self.home, {x=0, y=1, z=0}), 5, 1, 1)
                  if path then
                     self.path = path
                     self.step = 2
                     self.state = 'traveling'
                  end
               end
            end
         end
      elseif moveresults.collides then
         local hit_node = moveresults.collisions[1] and moveresults.collisions[1].type == 'node'
         if hit_node then
            local node_pos = moveresults.collisions[1].node_pos
            local node = core.get_node(node_pos)
            if core.get_item_group(node.name, 'storage') > 0 then
               local resources = kobo.resources[self.owner]
               if self.mat == 'stone' then
                  resources.stone = resources.stone + self.inv
               elseif self.mat == 'metal' then
                  resources.metal = resources.metal + self.inv
               end
               self.inv = 0
               self.state = 'idle'
               local player = core.get_player_by_name(self.owner)
               kobo.hud_refresh(player)
            elseif core.get_item_group(node.name, 'stone_mine') > 0 then
               local node_pos = moveresults.collisions[1].node_pos
               local node = core.get_node(node_pos)
               local def = core.registered_nodes[node.name]
               local material = def._material
               self.object:set_velocity({x=0, y=0, z=0})
               self.last_job = node_pos
               self.state = 'working'
               self.mat = 'stone'
            elseif core.get_item_group(node.name, 'metal_mine') > 0 then
               local node_pos = moveresults.collisions[1].node_pos
               local node = core.get_node(node_pos)
               local def = core.registered_nodes[node.name]
               local material = def._material
               self.object:set_velocity({x=0, y=0, z=0})
               self.last_job = node_pos
               self.state = 'working'
               self.mat = 'metal'
            end
         end
      end
   end,

   on_punch = function(self, puncher)
      self.object:remove()
   end,

   on_rightclick = function(self, clicker)
      local player_name = clicker:get_player_name()
      if self.owner == player_name or core.check_player_privs(clicker, {server = true}) then
         core.show_formspec(player_name, 'kobo:miner_overview', miner_overview(self))
      end
   end,

})
