--
-- DELME
-- 
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 (nil, name)
    self.a = storage
end    
-------------
function evaluator_enabled:evaluate ()
    return xr_logic.is_active (self.object, self.a)
end
----------------------------------------------------------------------------------------

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


----------------------------------------------------------------------------------------
class "evaluator_raid" (property_evaluator)
-------------
function evaluator_raid:__init (name, storage) super (nil, name)
    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 (storage.npc)
	self.stage = 0
	self.sub_stage = 0
    self.current_phrase = 0
end
-------------
function action_patrol:initialize ()
    action_base.initialize (self)
    
	self.move_mgr:initialize ()
	
	self.object:set_node_evaluator()
	self.object:set_path_evaluator()
	self.object:set_desired_position()
	self.object:set_desired_direction()

	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
    
     self.sounds =
                 { 
                 rnd = 100,
                 maxidle = 1,
                 sumidle = 0,
                 themes = { "patrol_radio_1" },
                 last_num = 0
                 }
    self.sounds["seq_cnt"] = 0
	
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 ()
    
    local obj = self.object:object ("hand_radio")
    if obj ~= nil then
       obj:enable_attachable_item (false)
    end    
	self.move_mgr:finalize ()
    action_base.finalize (self)
end
-------------
function action_patrol:reset_scheme ()
	if self.a.path_walk_info == nil then
	   self.a.path_walk_info = utils.path_parse_waypoints(self.a.patrol_path)
	end
	if self.a.path_look_info == nil then
	   self.a.path_look_info = utils.path_parse_waypoints(self.a.patrol_look)
	end   
	self.move_mgr:reset(self.a.patrol_path, self.a.path_walk_info, self.a.patrol_look, self.a.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)
	   printf("SET_SIGHT!!!action_patrol:callback")
       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)
           else
              local actor = level.actor()
              if actor then
                 if xr_logic.try_switch_to_another_section (self.object, self.a, actor) then
                    return
                 end
              end
           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
          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.sounds["seq_cnt"] < 8 then
          self.object:add_animation ("raciya_2", true)
       end
       if self.sounds["seq_cnt"] >= 7 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_sound.sound_update(self.object, self.sounds)
       end
       return false
    end

    if self.sub_stage == 2 and count == 1 then
       local obj = self.object:object ("hand_radio")
       if obj ~= nil then
          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 = #db.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)
        db.storage[self.object:id()].followers[a].direction = vec
        db.storage[self.object:id()].followers[a].distance = 3.0
    end
end
-------------
function action_patrol:set_soldier_positions_raid ()
    local size = #db.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
        db.storage[self.object:id()].followers[count].direction = v
        db.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 = #db.storage[self.object:id()].followers
    if size == 0 then return end
    for a = 1, size, 1 do
        db.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)
	  printf("SET_SIGHT!!!action_escape:initialize")
    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 = #db.storage[self.object:id()].followers
    if size == 0 then return end
    for a = 1, size, 1 do
        db.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 (storage.npc)
end
-------------
function action_raid:initialize ()
    action_base.initialize (self)
    
	self.move_mgr:initialize ()
        
    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: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 ()
    if self.a.raid_path == nil then return end
	if self.a.raid_walk_info == nil then
	   self.a.raid_walk_info = utils.path_parse_waypoints(self.a.raid_path)
	end
	if self.a.raid_look_info == nil then
	   self.a.raid_look_info = utils.path_parse_waypoints(self.a.raid_look)
	end   
	self.move_mgr:reset(self.a.raid_path, self.a.raid_walk_info, self.a.raid_look, self.a.raid_look_info, self.a.team, nil, {obj = self, func = self.callback})
	local id = self.object:id()
    local size = #db.storage[id].followers
    if size == 0 then return end
    for a = 1, size, 1 do
        db.storage[id].followers[a].raid_process = true
        --local npc = db.storage[self.object:id()].followers[a].npc
        --db.storage[npc:id ()].patrol.raid_process = true
    end
end	
-------------
function action_raid:callback (mode, number)
    if number == 0 then 
       self.a.raid_process = false 
       self.a.raid_enabled = false
       return true
    end   
    return false
end
----------------------------------------------------------------------------------------


----------------------------------------------------------------------------------------
function add_to_binder (npc, ini, scheme, section, storage)

    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 ("comm_ptr_enabled", storage))
    manager:add_evaluator (properties["escape"], this.evaluator_escape ("comm_ptr_escape_enabled", storage))
    manager:add_evaluator (properties["raid"], this.evaluator_raid ("comm_ptr_raid_enabled", storage))
    
    local action = this.action_patrol ("patrol", storage)
    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))
    xr_motivator.addCommonPrecondition(action)
    action:add_effect (world_property(properties["enabled"], false))
    manager:add_action (operators["patrol"], action)

    xr_logic.subscribe_action_for_events (npc, storage, action)
    
    action = this.action_escape ("escape", storage)
    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))
    xr_motivator.addCommonPrecondition(action)
    action:add_effect (world_property(properties["enabled"], false))
    manager:add_action (operators["escape"], action)

    local action_new = this.action_raid ("raid", storage)
    action_new:add_precondition (world_property(stalker_ids.property_alive, true))
    action_new:add_precondition (world_property(stalker_ids.property_enemy, false))
    action_new:add_precondition (world_property(properties["raid"], true))
    action_new:add_precondition (world_property(properties["enabled"], true))
    xr_motivator.addCommonPrecondition(action_new)
    action_new:add_effect (world_property(properties["raid"], false))
    manager:add_action (operators["raid"], action_new)
    
    xr_logic.subscribe_action_for_events (npc, storage, action_new)
    
    action = manager:action (xr_actions_id.alife)
    action:add_precondition (world_property(properties["enabled"], false))
    
    --this.set_patrol (npc)

end
----------------------------------------------------------------------------------------
function set_scheme (npc, ini, scheme, section, gulag_name)

	local st = xr_logic.assign_storage_and_bind (npc, ini, scheme, section)
	st.logic = xr_logic.cfg_get_switch_conditions (ini, section, npc)
	st.patrol_path  = utils.cfg_get_string (ini, section, "patrol_path", npc, true,  gulag_name)
	st.patrol_look  = utils.cfg_get_string (ini, section, "patrol_look", npc, false, gulag_name)
	st.escape_path  = utils.cfg_get_string (ini, section, "escape_path", npc, false, gulag_name)
	st.raid_enabled = utils.cfg_get_bool   (ini, section, "raid_enabled",npc, false)
	st.raid_path    = utils.cfg_get_string (ini, section, "raid_path",   npc, false, gulag_name)
	st.raid_look    = utils.cfg_get_string (ini, section, "raid_look",   npc, false, gulag_name)
	st.team         = utils.cfg_get_string (ini, section, "team",        npc, false, gulag_name)

	st.path_walk_info = nil -- Будут инициализированы в reset(), сейчас пути могут еще
	st.path_look_info = nil -- быть не загружены.
	st.raid_walk_info = nil
	st.raid_look_info = nil
	st.raid_process = false
end

