core.register_entity('ls_mobs:womble', {
   initial_properties = {
      visual = 'mesh',
      mesh = 'ls_mobs_womble.b3d',
      textures = {'ls_mobs_womble.png'},
      visual_size = {x=10, y=10},
      physical = true,
      collide_with_objects = true,
      collisionbox = {-0.4, -0.5, -0.4, 0.4, .5, 0.4},
      automatic_face_movement_dir = 90.0
   },

   on_activate = function(self, staticdata, dtime_s)
      local data = core.deserialize(staticdata)
      if data then
         self.health = data.health
         self.node_timer = data.node_timer
         self.state = data.state
         self.path = data.path
         self.step = data.step
         self.last_job = data.last_job
         self.following_player = data.following_player
         self.wander_count = data.wander_count
      else
         self.last_job = self.object:get_pos()
         self.health = math.random(20,40)
         self.state = 'idle'
         self.step = 0
         self.wander_count = 0
      end
   end,

   get_staticdata = function(self)
      local data ={}
      data.health = self.health
      data.node_time = self.node_timer
      data.state = self.state
      data.path = self.path
      data.step = self.step
      data.last_job = self.last_job
      data.following_player = self.following_player
      data.wander_count = self.wander_count
      return core.serialize(data)
   end,

   on_step = function(self, dtime, moveresults)
      if 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, 'attack') > 0 then
               self.state = 'attack'
               self.object:set_velocity({x=0, y=0, z=0})
            else
               local axis = moveresults.collisions[1].axis
               if axis == 'x' or axis == 'z' then
                  local above_pos = vector.add(node_pos, {x=0, y=1, z=0})
                  local old_velocity = moveresults.collisions[1].old_velocity
                  self.object:set_pos(above_pos)
                  self.object:add_velocity(old_velocity)
               end
            end
         end
      end
      self.node_timer = (self.node_timer or 0) + dtime
      if self.node_timer > 1 then
         self.node_timer = 0
         local self_pos = self.object:get_pos()
         local below_pos = vector.subtract(self_pos, {x=0, y=1, z=0})
         local below_node = core.get_node(below_pos).name
         local vel = self.object:get_velocity()
         local speed = math.sqrt((vel.x*vel.x) + (vel.z*vel.z))
         if speed > 4 then
            local slow = vector.multiply(vel, .25)
            self.object:set_velocity(slow)
         end
         if below_node == 'air' then
            self.object:set_pos(below_pos)
         end
         if self.state == 'idle' then
            local objects = core.get_objects_inside_radius(self_pos, 15)
            for i = 1,#objects do
               if not objects[i]:is_player() then
                  objects[i] = nil
               end
            end
            if #objects > 0 then
               local low_dist = 15
               local player_name
               for _,player in pairs(objects) do
                  local player_pos = player:get_pos()
                  local dist = vector.distance(self_pos, player_pos)
                  if dist < low_dist then
                     low_dist = dist
                     player_name = player:get_player_name()
                  end
               end
               self.following_player = player_name
               self.state = 'following'
            else
               local pos1 = vector.add(self_pos, {x=-15, y=-5, z=-15})
               local pos2 = vector.add(self_pos, {x=15, y=5, z=15})
               local targets = core.find_nodes_in_area(pos1, pos2, 'group:attack')
               if #targets > 0 then
                  local target = ls_mobs.sort_targets(targets)
                  local pos1 = vector.add(target, {x=-1, y=-1, z=-1})
                  local pos2 = vector.add(target, {x=1, y=1, z=1})
                  local air = core.find_nodes_in_area(pos1, pos2, {'air'})
                  local light_level = core.get_node_light(air[1])
                  if light_level < 2 then
                     local path = ls_mobs.get_path(self_pos, target)
                     if path then
                        self.path = path
                        self.step = 2
                        self.state = 'traveling'
                     end
                  else
                     self.state = 'wandering'
                     local dir = vector.random_direction()
                     local clean_dir = vector.multiply(dir, {x=2, y=0, z=2})
                     self.object:set_velocity(clean_dir)
                  end
               else
                  self.state = 'wandering'
                  local dir = vector.random_direction()
                  local clean_dir = vector.multiply(dir, {x=2, y=0, z=2})
                  self.object:set_velocity(clean_dir)
               end
            end
         elseif self.state == 'traveling' then
            if #self.path > (self.step - 1) then
               local perhaps = vector.direction(self_pos, self.path[self.step])
               self.object:set_velocity({x = perhaps.x, y = 0, z = perhaps.z})
               local dif = vector.subtract(self_pos, self.path[self.step])
               if dif.y < 0 then
                  self.object:add_velocity({x=0, y=1.2, z=0})
               end
               self.step = self.step + 1
            else
               local target = core.find_node_near(self_pos, 1, 'group:attack', true)
               self.object:set_velocity({x=0, y=0, z=0})
               self.state = 'attack'
            end
         elseif self.state == 'attack' then
            local target = core.find_node_near(self_pos, 1, 'group:attack', true)
            if target and not self.break_time then
               local node = core.get_node(target)
               local def = core.registered_nodes[node.name]
               local break_time = def.break_time
               if not break_time then
                  break_time = 8
               end
               self.break_time = break_time
               if core.get_item_group(node.name, 'beacon') > 0 then
                  local meta = core.get_meta(target)
                  local player_name = meta:get_string('player_name')
                  local key = core.pos_to_string(target)
                  local data = ls_crystal.data[player_name][key]
                  local links = data.links
                  local chance = math.random(1,3)
                  if links >= chance then
                     self.break_time = 459
                  end
               end
            elseif self.break_time and self.break_time < 60 then
               self.break_time = self.break_time - 1
               if self.break_time <= 0 then
                  if target then
                     --swap to broken version
                     core.remove_node(target)
                  end
                  self.state = 'idle'
               end
            else
               self.state = 'idle'
            end
         elseif self.state == 'following' then
            if self.following_player then
               local player = core.get_player_by_name(self.following_player)
               local player_pos = player:get_pos()
               local distance = vector.distance(player_pos, self_pos)
               if distance < 2 then
                  player:punch(self.object, 1.0, {
                     full_punch_interval = 1.0,
                     damage_groups = {fleshy=2}
                     }, nil)
               elseif distance < 20 then
                  local light_level = core.get_node_light(player_pos)
                  if light_level < 7 then
                     local perhaps = vector.direction(self_pos, player_pos)
                     perhaps = vector.multiply(perhaps, 3)
                     self.object:set_velocity({x = perhaps.x, y = 0, z = perhaps.z})
                  else
                     local perhaps = vector.direction(self_pos, player_pos)
                     perhaps = vector.multiply(perhaps, -3)
                     self.object:set_velocity({x = perhaps.x, y = 0, z = perhaps.z})
                     self.state = 'wandering'
                  end
               else
                  self.state = 'idle'
               end
            else
               self.state = 'idle'
            end
         elseif self.state == 'wandering' then
            self.wander_count = self.wander_count or 1
            self.step = self.step + 1
            if self.step > 8 then
               self.state = 'idle'
               self.step = 0
               self.wander_count = self.wander_count + 1
            end
            if self.wander_count > 5 then
               self.object:remove()
            end
         else
            self.state = 'idle'
         end
      end
   end,

   on_death = function(self, killer)
      local pos = self.object:get_pos()
      local crystal_chance = math.random(1,3)
      local metal_chance = math.random(1,2)
      local meat_chance = math.random(1,4)
      if crystal_chance == 1 then
         local clean_dir = vector.multiply(vector.random_direction(), {x=1,y=0,z=1})
         pos = vector.add(clean_dir, pos)
         core.add_item(pos, 'ls_crystal:lightshard_on')
      end
      if metal_chance == 1 then
         local metal_count = math.random(1,4)
         local clean_dir = vector.multiply(vector.random_direction(), {x=1,y=0,z=1})
         pos = vector.add(clean_dir, pos)
         core.add_item(pos, 'ls_items:metal_lump '..metal_count)
      end
      if meat_chance == 1 then
         local clean_dir = vector.multiply(vector.random_direction(), {x=1,y=0,z=1})
         pos = vector.add(clean_dir, pos)
         core.add_item(pos, 'ls_items:meat_raw')
      end
   end,

   on_punch = function(self, puncher)
      local player_name = puncher:get_player_name()
      self.object:set_velocity({x=0, y=0, z=0})
      self.state = 'following'
      self.following_player = player_name
   end,
})
