--******************************************************************************************
function public.Init( pos_z )

  local impl_module_name = nil;

  if ( _G[ "int_taskheader" ] ) then

    impl_module_name = "int_taskheader_taskpanel_impl";

  end;

  interface.LoadImplementation( "taskpanel", impl_module_name );
  ObjAttach( "int_taskpanel", interface.originhub );
  ObjSet( "int_taskpanel", { pos_z = pos_z } );
  private.event_anim_end = {};
  private.m_tasks_data = nil;
  private.already_hide = nil;

  MsgSubscribe( Command_Interface_UpdateTextures, private.WideScreenUpdate );
  MsgSubscribe( Command_TaskPanel_DecreaseZ, private.DecreaseZ );
  MsgSubscribe( Command_TaskPanel_IncreaseZ, private.IncreaseZ );
  MsgSubscribe( Event_Level_CheatKeyPressed, private.HotKey );

end;
--******************************************************************************************
function public.Destroy()

  MsgUnsubscribe( Command_Interface_UpdateTextures, private.WideScreenUpdate );
  MsgUnsubscribe( Command_TaskPanel_DecreaseZ, private.DecreaseZ );
  MsgUnsubscribe( Command_TaskPanel_IncreaseZ, private.IncreaseZ );
  MsgUnsubscribe( Event_Level_CheatKeyPressed, private.HotKey );

end;
--******************************************************************************************
function public.EventAnimEnd( event_id )

  local event_params = private.event_anim_end[ event_id ];

------------------------------------------------------------------------------------
  if ( event_id == "show" ) then

  ObjSet( "int_taskpanel", { input = true } );

------------------------------------------------------------------------------------
  elseif ( event_id == "hide" ) then

  ObjSet( "int_taskpanel", { active = false, visible = false } );

------------------------------------------------------------------------------------
  elseif ( event_id == "taskheader_show" ) then

  ObjSet( "int_taskpanel", { input = true } );

------------------------------------------------------------------------------------
  elseif ( event_id == "taskheader_hide" ) then

  ObjSet( "int_taskpanel", { active = false, visible = false } );

------------------------------------------------------------------------------------
  elseif ( string.find( event_id, "unmark_task" ) ) then

  local task_name   = event_params[ "name" ];

  local task_id     = private.task_id[ task_name ];
  local task_params = private.task_params[ task_id ];

  int_taskpanel_impl.SetTask( task_id, task_params );

  elseif ( string.find( event_id, "mark_task" ) ) then

  local task_name   = event_params[ "name" ];

  local task_id     = private.task_id[ task_name ];
  local task_params = private.task_params[ task_id ];

  int_taskpanel_impl.SetTask( task_id, task_params );

------------------------------------------------------------------------------------
  elseif ( string.find( event_id, "complete_task" ) ) then

    local task_name   = event_params[ "name" ];
    local object_name = event_params[ "game_name" ];
    local task_count  = event_params[ "count" ];

    local task_id     = private.task_id[ task_name ];
    local task_params = private.task_params[ task_id ];

    --DbgTrace( "!!! COMPLETE TASK END for "..object_name.." game name = "..object_name );

    --[[
    local item_obj_name = "fly_int_taskpanel_item_"..task_id.."_"..task_count;

    ObjDelete( item_obj_name );
    ]]

    int_taskpanel_impl.SetTask( task_id, task_params );

    ObjDelete( "object_name" );
    if private.m_tasks_data ~= nil then

      local all_collected = true;

      for i = 1, #private.m_tasks_data do
        if private.m_tasks_data[ i ].name == task_name then
          local collected = private.m_tasks_data[ i ].collected;
          local count = private.m_tasks_data[ i ].count;
          if count == collected then
            private.m_tasks_data[ i ].completed = 1;
          end;
        end;
        if private.m_tasks_data[ i ].completed ~= 1 then
          all_collected = false;
        end;
      end;

      if all_collected then
        MsgSend( Event_DialogHo_Show, {} );
      end;

    end;

  end;
------------------------------------------------------------------------------------

end;
--******************************************************************************************
function public.Switch()

  if ( _G[ "int_taskheader" ] ) then

    int_taskheader.MouseDown( "taskpanel" );

  end;

end;
--******************************************************************************************
function public.ShowForTaskHeader( ho_tasks )

  public.Show( ho_tasks, true );

end;
--******************************************************************************************
function public.HideForTaskHeader()

  public.Hide();

end;
--******************************************************************************************
function public.Show( ho_tasks, is_for_taskheader )

  if private.m_tasks_data then private.m_tasks_data = nil; end;

  private.m_tasks_data = ho_tasks;
  for i = 1, #private.m_tasks_data do
    private.m_tasks_data[ i ].collected = 0;
    private.m_tasks_data[ i ].completed = 0;
    if private.m_tasks_data[ i ].count == 0 then
      private.m_tasks_data[ i ].completed = 1;
    end;
  end;

  private.already_hide = false;

  ObjSet( "int_taskpanel", { active = true, visible = true } );

  --DbgTrace( "tasks count: "..#ho_tasks );

  private.task_id     = {};
  private.task_params = {};

  for i = 1, #ho_tasks, 1 do

    local task_name   = ho_tasks[ i ][ "name"   ]
    local task_count  = ho_tasks[ i ][ "count"  ];
    local task_marked = ho_tasks[ i ][ "marked" ];

    private.task_id[ task_name ] = i;
    private.task_params[ i ] =
    {
      name   = task_name,
      count  = task_count,
      marked = task_marked
    };
    int_taskpanel_impl.SetTask( i, private.task_params[ i ] );

  end;

  if ( is_for_taskheader == nil ) then

    local event_id = "show";
    private.event_anim_end[ event_id ] = {};
    int_taskpanel_impl.ShowAnim( event_id );

  elseif ( is_for_taskheader ) then

    local event_id = "taskheader_show";
    private.event_anim_end[ event_id ] = {};
    int_taskpanel_impl.TaskHeaderShowAnim( event_id );

  end;

end;
--******************************************************************************************
function public.CompleteTask( task_name, game_name )

    --DbgTrace( "TASK PANEL COMPLETE" );

  local answer = MsgSend( Request_Level_IsLoading, {} );
  if answer.loading == 1 then

    ObjDelete( game_name );
    game_name = "";    

  end;

  if game_name ~= "" then

    ObjSet( game_name, { input = false } );

  end;

  local task_count = 0;
  for i = 1, #private.m_tasks_data do
    local collected = private.m_tasks_data[ i ].collected;
    local count = private.m_tasks_data[ i ].count;
    if private.m_tasks_data[ i ].name == task_name then
      if collected < count then
        private.m_tasks_data[ i ].collected = collected + 1;
        collected = collected + 1;
        task_count = count - collected;
      end;    
    end;
  end;

  local task_id = private.task_id[ task_name ];
  private.task_params[ task_id ].count = task_count;

  if ( game_name ) then

    -- блок исключен за отсуствием необходимости
    -- мешает реализации анимаций с частицами по маске
    --[[
    local task_obj_name = "obj_int_taskpanel_task_"..task_id;
    local item_obj_name = "fly_int_taskpanel_item_"..task_id.."_"..task_count;

    local item_pos = GetObjPosByObj( game_name );
    
    ObjCreate( item_obj_name, "obj" );
    ObjSet( item_obj_name,
    {
      pos_x = item_pos[ 1 ],
      pos_y = item_pos[ 2 ],
      pos_z = 13
    } );
    ObjAttach( item_obj_name, InterfaceWidget_Top_Name );

    ObjSet( game_name, { pos_x = 0, pos_y = 0, pos_z = 13 } );
    ObjAttach( game_name, item_obj_name );

    local event_id = "complete_task_"..task_id.."_"..task_count;
    private.event_anim_end[ event_id ] = message_params;

    interface.taskpanel.Switch();
    interface.taskpanel.CompleteTaskAnim( item_obj_name, task_id, event_id );
    ]]

    local event_id = "complete_task_"..task_id.."_"..task_count;
    private.event_anim_end[ event_id ] = { name = task_name, game_name = game_name, task_count = count };

    public.Switch();
    int_taskpanel_impl.CompleteTaskAnim( game_name, task_id, task_count, event_id );

  end;

end;
--******************************************************************************************
function public.SetTaskMark( task_name, mark_state )
 
  local task_id = private.task_id[ task_name ];

  private.task_params[ task_id ].marked = mark_state;

  if     ( mark_state == 0 ) then

    local event_id = "unmark_task_"..task_name;
    private.event_anim_end[ event_id ] = { name = task_name, mark = mark_state };

    --interface.taskpanel.Switch();
    int_taskpanel_impl.UnmarkTaskAnim( task_id, event_id );

  elseif ( mark_state == 1 ) then

    local event_id = "mark_task_"..task_name;
    private.event_anim_end[ event_id ] = { name = task_name, mark = mark_state };

    --interface.taskpanel.Switch();
    int_taskpanel_impl.MarkTaskAnim( task_id, event_id );

  end;

end;
--******************************************************************************************
function public.ShowHoHint()

  if private.m_tasks_data == nil then return; end;

  local not_objects_task_counts = 0;
  local object_tasks = {};
  for i = 1, #private.m_tasks_data do
    if private.m_tasks_data[ i ].collected < private.m_tasks_data[ i ].count then

      local hint_objects = {};
      local hint = private.m_tasks_data[ i ].hint;
      for j = 1, #hint do
        for k = 1, #hint[ j ] do
          local params = ObjGet( hint[ j ][ k ] );
          if params ~= nil and params.input then
            table.insert( hint_objects, hint[ j ][ k ] );
          else
            hint_objects = {};
            break;
          end; 
          if #hint_objects > 0 then
            break;
          end;
        end;
        if #hint_objects > 0 then
          table.insert( object_tasks, hint_objects );
        else
          not_objects_task_counts = not_objects_task_counts + 1;
        end;
      end;

    end;
  end;

  if #object_tasks == 0 and not_objects_task_counts == 0 then
    DbgTrace( "Warning! No available tasks for hinterface." );
  else

    if #object_tasks > 0 then

      local index = math.random( 1, #object_tasks );
      local hint_table = { hint = {} };
      for i = 1, #object_tasks[ index ] do
        local objname = object_tasks[ index ][ i ];
        local pos = GetObjPosByObj( objname );
        --DbgTrace( pos[ 1 ].." "..pos[ 2 ].." "..objname );
        table.insert( hint_table.hint, { pos_x = pos[ 1 ], pos_y = pos[ 2 ], obj_name = objname } );
      end;
      MsgSend( Command_Effect_ShowHoHint, hint_table );

    else
      MsgSend( Event_HoHint_NoObjects, {} );
    end;

  end;

end;
--******************************************************************************************
function public.Hide( for_taskpanel )

  if ( not private.already_hide ) then

    private.already_hide = true;
    private.m_tasks_data = nil;

    ObjSet( "int_taskpanel", { input = false } );

    if ( not for_taskpanel ) then

      local event_id = "hide";
      private.event_anim_end[ event_id ] = {};
      int_taskpanel_impl.HideAnim( event_id );

    elseif ( for_taskpanel ) then
   
      local event_id = "taskheader_hide";
      private.event_anim_end[ event_id ] = {};
      int_taskpanel_impl.TaskHeaderHideAnim( event_id );

    end;

  end;

end;
--******************************************************************************************
function public.StdFlyAnimation( item_obj_name, task_obj_name, trigger_end, reduced_time )

  reduced_time = reduced_time or 0;

  SendMessage( Command_Transporter_MoveObject,
  {
    type       = Trans_SceneToTaskPanel,
    obj_name   = item_obj_name,
    toobj_name = task_obj_name,
    end_trig   = trigger_end,
    red_time   = reduced_time
  } );

end;
--******************************************************************************************
function private.HotKey( msg, params )

  if params.key == 13 --[[Enter - key]] then  

  elseif params.key == 32 --[[Space - key]] then  
    MsgSend( Event_DialogHo_Show, {} );

  end;

end;
--******************************************************************************************
function private.WideScreenUpdate()

  interface.WideScreenUpdate( "taskpanel" );

end;
--******************************************************************************************
function private.StdFlyAnimation( item_obj_name, task_obj_name, trigger_end, reduced_time )

  reduced_time = reduced_time or 0;

  SendMessage( Command_Transporter_MoveObject,
  {
  type       = Trans_SceneToTaskPanel,
  obj_name   = item_obj_name,
  toobj_name = task_obj_name,
  end_trig   = trigger_end,
  red_time   = reduced_time
  } );

end;
--******************************************************************************************
function private.DecreaseZ()
  ObjSet( "int_taskpanel", { pos_z = ObjGet( "int_taskpanel" ).pos_z - 1 } );
end;
--******************************************************************************************
function private.IncreaseZ()
  ObjSet( "int_taskpanel", { pos_z = ObjGet( "int_taskpanel" ).pos_z + 1 } );
end;
--******************************************************************************************