local leader_no_command             = 0
local leader_move                   = 1
local leader_stop                   = 2
local leader_speak                  = 3
local leader_speak_enable           = 4
local leader_return                 = 5
local leader_free                   = 6

----------------------------------------------------------------------------------------
class "evaluator_enabled" (property_evaluator)
-------------
function evaluator_enabled:__init (name, storage) super ()
    self.a = storage
end    
-------------
function evaluator_enabled:evaluate ()
    return self.a.enabled
end
----------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
class "evaluator_escape" (property_evaluator)
-------------
function evaluator_escape:__init (name, storage) super ()
    self.a = storage
end
-------------
function evaluator_escape:evaluate ()
    if self.a.escape_path == nil then return false end
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return false end
    for count = 1, size, 1 do
        if xr_motivator.storage[self.object:id()].followers[count].npc:alive () == false then
            return true
        end
    end        
    return false
end
----------------------------------------------------------------------------------------


----------------------------------------------------------------------------------------
class "evaluator_raid" (property_evaluator)
-------------
function evaluator_raid:__init (name, storage) super ()
    self.a = storage
end    
-------------
function evaluator_raid:evaluate ()
    return self.a.raid_process
end
----------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------
class "action_patrol" (action_base)
-------------
function action_patrol:__init (name, storage) super (nil, name)
    self.a = storage
	self.move_mgr = move_mgr.move_mgr ()
	self.path_walk_info = nil
    self.path_look_info = nil
	self.stage = 0
	self.sub_stage = 0
    self.current_phrase = 0
end
-------------
function action_patrol:initialize ()
    action_base.initialize (self)
	self.object:set_node_evaluator()
	self.object:set_path_evaluator()
	self.object:set_desired_position()
	self.object:set_desired_direction()

	self.move_mgr:initialize(self.object)

	if self.path_walk_info == nil then
		self.path_walk_info = utils.path_parse_waypoints(self.a.patrol_path)
	end

	if self.path_look_info == nil then
		self.path_look_info = utils.path_parse_waypoints(self.a.look_path)
	end
	
	self:reset_scheme()
	
	self.stage = 0
	
    local obj = self.object:object ("hand_radio")
    if obj ~= nil then
       --self.object:enable_attachable_item (true)
       printf ("DISABLE RADIO 1")
       obj:enable_attachable_item (false)
    end
	
end
-------------
function action_patrol:execute ()
    action_base.execute (self)

    
    if self.stage == 0 then    
	   self.move_mgr:update ()
	   --update soldier positions
       if self.a.raid_enabled == false then 
          self:set_soldier_positions ()
       else 
          self:set_soldier_positions_raid ()
       end
       --update soldier states
	   if self.move_mgr.moving == true then 
	      self:set_command (leader_move) 
	   else   
	      self:set_command (leader_stop) 
	   end
	elseif self.stage == 1 then 
	      self:set_command (leader_stop)  
	      if self:process_radio () == true then
             self.move_mgr:update_movement_state ()
	         self.stage = 0
	      end
	end
	
end    
-------------
function action_patrol:finalize ()
	self.move_mgr:finalize ()
    action_base.finalize (self)
end
-------------
function action_patrol:reset_scheme ()
	self.move_mgr:reset(self.a.patrol_path, self.path_walk_info, self.a.look_path, self.path_look_info, nil, nil, {obj = self, func = self.callback})
end	
-------------
function action_patrol:callback (mode, number)
    if number == 0 then 
       self.object:clear_animations ()
       self.object:set_movement_type (move.stand)
       self.object:add_animation ("raciya_0", true)
       self.object:add_animation ("raciya_1", true)
       self.object:add_animation ("raciya_2", true)
       self.object:set_movement_type (move.stand)
       self.object:set_sight (look.path_dir, nil, 0)
       self.sub_stage = 0
       self.current_phrase = 1
       self.stage = 1
       return true
    elseif number == 1 then
           local st = xr_gulag.isUnderFraction (self.object)
           if st ~= nil then
              xr_gulag.resetJob (st, self.object)
              self:set_command (leader_free)  
           end
    elseif number == 2 then
           self.a.raid_process = true
    end
    return false
end
-------------
function action_patrol:process_radio ()
    local count = self.object:animation_count ()

    if self.sub_stage == 0 and count == 2 then
       local obj = self.object:object ("hand_radio")
       if obj ~= nil then
          --printf ("ENABLE RADIO 1")
          --self.object:enable_attachable_item (true)
          --printf ("ENABLE RADIO 2")
          obj:enable_attachable_item (true)
       end
    end

    if self.sub_stage == 0 and count == 1 then
       self.sub_stage = 1
       return false
    end

    if self.sub_stage == 1 then
       if count == 1 and self.current_phrase < 8 then
          self.object:add_animation ("raciya_2", true)
       end
       if self.object:active_sound_count () == 0 then
          if self.current_phrase >= 8 then
             self.sub_stage = 2
             self.object:clear_animations ()
             self.object:add_animation ("raciya_3", true)
             self.object:add_animation ("raciya_4", true)
          else
             xr_sounds.play_sound (self.object, 0, "commander_radio", 1, self.current_phrase)
             self.current_phrase = self.current_phrase + 1
          end
       return false
       end
    end

    if self.sub_stage == 2 and count == 1 then
       local obj = self.object:object ("hand_radio")
       if obj ~= nil then
          printf ("DISABLE RADIO")
          --self.object:enable_attachable_item (false)
          obj:enable_attachable_item (false)
       end
    end

    if count ~= 0 then
       return false
    end
    return true
end
-------------
function action_patrol:set_soldier_positions ()
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return end
    local dir = self.object:direction ()
    dir.y = 0.0
    dir:normalize ()
    local step = 180.0 / size
    local angle = 90.0
    for a = 1, size, 1 do
        if a == 1 then angle = angle + step * 0.5
        else angle = angle + step end
        local vec = vector_rotate_y (dir, angle)
        xr_motivator.storage[self.object:id()].followers[a].direction = vec
        xr_motivator.storage[self.object:id()].followers[a].distance = 3.0
    end
end
-------------
function action_patrol:set_soldier_positions_raid ()
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return end
    local dir = self.object:direction ()
    dir.y = 0.0
    dir:normalize ()
    local dist = 5.0
    local side = false
    local v = vector ():set (0, 0, 0)
    for count = 1, size, 1 do
        if side == false then
           v = vector_rotate_y (dir, -90.0)
           side = true
        else
           v = vector_rotate_y (dir, 90.0)
           side = false
        end
        xr_motivator.storage[self.object:id()].followers[count].direction = v
        xr_motivator.storage[self.object:id()].followers[count].distance = dist
        if count == 2 or count == 4 or count == 6 or count == 8 or count == 10 then
           dist = dist + dist
        end
    end

end
-------------
function action_patrol:set_command (command)
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return end
    for a = 1, size, 1 do
        xr_motivator.storage[self.object:id()].followers[a].leader_command = command
    end
end
---------------------------------------------------------------------------------------------------------------------


---------------------------------------------------------------------------------------------------------------------
class "action_escape" (action_base)
-------------
function action_escape:__init (name, storage) super (nil, name)
    self.a = storage
end
-------------
function action_escape:initialize ()
    action_base.initialize (self)
    
    if self.a.escape_path == nil then
       utils.abort ("Escape path not defined for patrol soldier %s", self.object:name ())
    end
    
    self.object:clear_animations          ()
    self.object:set_node_evaluator        ()
    self.object:set_path_evaluator        ()
    self.object:set_desired_position      ()
    self.object:set_desired_direction     ()
    
    self.object:set_item                  (object.activate, self.object:best_weapon ())
    self.object:set_detail_path_type      (move.line)
    self.object:set_body_state            (move.standing)
    self.object:set_path_type             (game_object.patrol_path)
    self.object:set_patrol_path           (self.a.escape_path, patrol.nearest, patrol.continue, true)
    self.object:set_movement_type         (move.run)
    self.object:set_mental_state          (anim.danger)
    self.object:set_sight                 (look.path_dir, nil, 0)

    self.object:set_callback (self, "move_callback", game_object.movement)
    
end
-------------
function action_escape:execute ()
    action_base.execute (self)
    self:set_command (leader_return)
end    
-------------
function action_escape:finalize ()
    action_base.finalize (self)
end
-------------
function action_escape:move_callback (obj, action_type, index)
    if index == -1 then return end
    if patrol (self.object:patrol ()):flag (index, 0) == true then
       self.a.enabled = false
       local st = xr_gulag.isUnderFraction (self.object)
       if st ~= nil then
          xr_gulag.resetJob (st, self.object)
       end
    end    
end
----------------------------------------------------------------------------------------
function action_escape:set_command (command)
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return end
    for a = 1, size, 1 do
        xr_motivator.storage[self.object:id()].followers[a].leader_command = command
    end
end




---------------------------------------------------------------------------------------------------------------------
class "action_raid" (action_base)
-------------
function action_raid:__init (name, storage) super (nil, name)
    self.a = storage
	self.move_mgr = move_mgr.move_mgr ()
	self.path_walk_info = nil
    self.path_look_info = nil
end
-------------
function action_raid:initialize ()
    action_base.initialize (self)
    
    if self.a.raid_path == nil or self.a.raid_look == nil then
       utils.abort ("Raid path not defined for patrol soldier %s", self.object:name ())
    end
    
    self.object:clear_animations          ()
    self.object:set_node_evaluator        ()
    self.object:set_path_evaluator        ()
    self.object:set_desired_position      ()
    self.object:set_desired_direction     ()

	self.move_mgr:initialize(self.object)

	if self.path_walk_info == nil then
		self.path_walk_info = utils.path_parse_waypoints(self.a.raid_path)
	end

	if self.path_look_info == nil then
		self.path_look_info = utils.path_parse_waypoints(self.a.raid_look)
	end
	
	self:reset_scheme ()
end
-------------
function action_raid:execute ()
    action_base.execute (self)
    
    self.move_mgr:update ()
    
end    
-------------
function action_raid:finalize ()
	self.move_mgr:finalize ()
    action_base.finalize (self)
end
-------------
function action_raid:reset_scheme ()
	self.move_mgr:reset(self.a.raid_path, self.path_walk_info, self.a.raid_look, self.path_look_info, self.a.team, nil, {obj = self, func = self.callback})
    local size = table.getn (xr_motivator.storage[self.object:id()].followers)
    if size == 0 then return end
    for a = 1, size, 1 do
        local npc = xr_motivator.storage[self.object:id()].followers[a].npc
        xr_motivator.storage[npc:id ()].patrol.raid_process = true
    end
end	
-------------
function action_raid:callback (mode, number)
    if number == 0 then 
       self.a.raid_process = false 
       return true
    end   
    return false
end
----------------------------------------------------------------------------------------


----------------------------------------------------------------------------------------
function add_to_binder (npc, char_ini)

    local operators	= {}
    local properties  = {}
    
    properties["enabled"] = xr_evaluators_id.sidor_ptr
    properties["escape"]  = xr_evaluators_id.sidor_ptr + 1
    properties["raid"]    = xr_evaluators_id.sidor_ptr + 2
    
    operators["patrol"] = xr_actions_id.sidor_act_ptr
    operators["escape"] = xr_actions_id.sidor_act_ptr + 1
    operators["raid"]   = xr_actions_id.sidor_act_ptr + 2
    
    local manager = npc:motivation_action_manager()

    manager:add_evaluator (properties["enabled"], this.evaluator_enabled ("patrol_enabled", xr_motivator.storage[npc:id()].patrol))
    manager:add_evaluator (properties["escape"], this.evaluator_escape ("escape_enabled", xr_motivator.storage[npc:id()].patrol))
    manager:add_evaluator (properties["raid"], this.evaluator_raid ("raid_enabled", xr_motivator.storage[npc:id()].patrol))
    
    local action = this.action_patrol ("patrol", xr_motivator.storage[npc:id()].patrol)
    action:add_precondition (world_property(stalker_ids.property_alive, true))
    action:add_precondition (world_property(stalker_ids.property_enemy, false))
    action:add_precondition (world_property(properties["escape"], false))
    action:add_precondition (world_property(properties["raid"], false))
    action:add_precondition (world_property(properties["enabled"], true))
    action:add_effect (world_property(properties["enabled"], false))
    manager:add_action (operators["patrol"], action)
    
    action = this.action_escape ("escape", xr_motivator.storage[npc:id()].patrol)
    action:add_precondition (world_property(stalker_ids.property_alive, true))
    action:add_precondition (world_property(stalker_ids.property_enemy, false))
    action:add_precondition (world_property(properties["escape"], true))
    action:add_precondition (world_property(properties["raid"], false))
    action:add_precondition (world_property(properties["enabled"], true))
    action:add_effect (world_property(properties["enabled"], false))
    manager:add_action (operators["escape"], action)

    action = this.action_raid ("raid", xr_motivator.storage[npc:id()].patrol)
    action:add_precondition (world_property(stalker_ids.property_alive, true))
    action:add_precondition (world_property(stalker_ids.property_enemy, false))
    action:add_precondition (world_property(properties["raid"], true))
    action:add_precondition (world_property(properties["enabled"], true))
    action:add_effect (world_property(properties["raid"], false))
    manager:add_action (operators["raid"], action)
    
    action = manager:action (stalker_ids.action_puzzle_solver)
    action:add_precondition (world_property(properties["enabled"], false))
    
    this.set_patrol (npc)

end
----------------------------------------------------------------------------------------
function set_patrol (npc, enabled, patrol_path, look_path, escape_path, raid_enabled, raid_path, raid_look, raid_process, team)
  local char_ini = npc:spawn_ini()
  local st = xr_motivator.storage[npc:id()].patrol

  st.npc_id = npc:id ()
  st.first_init = true

    if enabled == nil then
       if char_ini:section_exist ("patrol") == true and char_ini:line_exist("patrol", "enabled") == true then
          st.enabled = char_ini:r_bool("patrol", "enabled")
       else
          st.enabled = false
       end
    else
       st.enabled = enabled
    end

    if patrol_path == nil then
       if char_ini:section_exist ("patrol") == true and char_ini:line_exist("patrol", "patrol_path") == true then
          st.patrol_path = char_ini:r_string("patrol", "patrol_path")
       else
          st.enabled = false
       end
    else
       st.patrol_path = patrol_path
    end

    if look_path == nil then
       if char_ini:section_exist ("patrol") == true and char_ini:line_exist("patrol", "patrol_look") == true then
          st.look_path = char_ini:r_string("patrol", "patrol_look")
       else
          st.look_path = nil
       end
    else
       st.look_path = look_path
    end
    
    if escape_path == nil then
       if char_ini:section_exist ("patrol") == true and char_ini:line_exist("patrol", "escape_path") == true then
          st.escape_path = char_ini:r_string("patrol", "escape_path")
       else
          st.escape_path = nil
       end
    else
       st.escape_path = escape_path
    end

    if raid_enabled == nil then
       if char_ini:section_exist ("patrol") == true and char_ini:line_exist ("patrol", "raid_enabled") == true then
          st.raid_enabled = char_ini:r_bool ("patrol", "raid_enabled")
       else
          st.raid_enabled = false
       end
    else
       st.raid_enabled = raid_enabled
    end

    if raid_path == nil then
      if char_ini:section_exist ("patrol") == true and char_ini:line_exist ("patrol", "raid_path") == true then
          st.raid_path = char_ini:r_string ("patrol", "raid_path")
      else
          st.raid_path = st.patrol_path
      end
    else
       st.raid_path = raid_path
    end

    if raid_look == nil then
      if char_ini:section_exist ("patrol") == true and char_ini:line_exist ("patrol", "raid_look") == true then
          st.raid_look = char_ini:r_string ("patrol", "raid_look")
      else
          st.raid_look = nil
      end
    else
       st.raid_path = raid_look
    end
    
    if raid_process == nil then
       st.raid_process = false
    else
       st.raid_process = raid_process
    end
    
    if team == nil then
      if char_ini:section_exist ("patrol") == true and char_ini:line_exist ("patrol", "team") == true then
          st.team = char_ini:r_string ("patrol", "team")
      else
          st.team = nil
      end
    else
       st.team = team
    end
    
  xr_motivator.checkStorage (npc)

  st.first_init = true

  xr_state.change_state(npc, xr_state.stand, false)
end


