/**
  * Get logs of job
  *
  * @param array $task_ids list of tasks id
  * @return array
  */
 function getJoblogs($task_ids = array())
 {
     global $DB;
     $debug_mode = $_SESSION['glpi_use_mode'] == Session::DEBUG_MODE;
     $runclass = new PluginFusioninventoryTaskjobstate();
     $run_states = $runclass->getStateNames();
     $query_where = array();
     $query_where[] = "WHERE 1";
     if (isset($_SESSION['glpiactiveentities_string'])) {
         $query_where[] = getEntitiesRestrictRequest("AND", 'task');
     }
     if (is_array($task_ids) and count($task_ids) > 0) {
         $query_where[] = "AND task.`id` IN (" . implode(",", $task_ids) . ")";
     }
     // quickly filter empty WHERE entry
     $query_where = array_filter($query_where);
     $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('job.targets', 'job.`targets`'));
     $fieldmap = array();
     foreach ($query_fields as $index => $key) {
         $fieldmap[$key[0]] = $index;
     }
     $query_select = array();
     foreach ($query_fields as $index => $key) {
         $query_select[] = $key[1] . " AS '" . $key[0] . "'";
     }
     $query_joins = array();
     $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", "  ON job.`plugin_fusioninventory_tasks_id` = task.`id`", "  AND task.`is_active` = 1"));
     $data_structure = array('query' => implode("\n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_taskjobs` as job", implode("\n", $query_joins), implode("\n", $query_where))), 'result' => null);
     $data_structure['result'] = $DB->query($data_structure['query']);
     //Results grouped by tasks > jobs > jobstates
     $logs = array();
     //Target cache (used to speed up data formatting)
     $targets_cache = array();
     $expanded = array();
     if (isset($_SESSION['plugin_fusioninventory_tasks_expanded'])) {
         $expanded = $_SESSION['plugin_fusioninventory_tasks_expanded'];
     }
     while ($result = $data_structure['result']->fetch_row()) {
         $task_id = $result[$fieldmap['task.id']];
         if (!array_key_exists($task_id, $logs)) {
             $logs[$task_id] = array('task_name' => $result[$fieldmap['task.name']], 'task_id' => $result[$fieldmap['task.id']], 'expanded' => false, 'jobs' => array());
         }
         if (isset($expanded[$task_id])) {
             $logs[$task_id]['expanded'] = $expanded[$task_id];
         }
         $job_id = $result[$fieldmap['job.id']];
         $jobs_handle =& $logs[$task_id]['jobs'];
         if (!array_key_exists($job_id, $jobs_handle)) {
             $jobs_handle[$job_id] = array('name' => $result[$fieldmap['job.name']], 'id' => $result[$fieldmap['job.id']], 'method' => $result[$fieldmap['job.method']], 'targets' => array());
         }
         $targets = importArrayFromDB($result[$fieldmap['job.targets']]);
         $targets_handle =& $jobs_handle[$job_id]['targets'];
         $agent_state_types = array('agents_prepared', 'agents_cancelled', 'agents_running', 'agents_success', 'agents_error', 'agents_notdone');
         if ($result[$fieldmap['job.method']] == 'networkinventory') {
             $pfNetworkinventory = new PluginFusioninventoryNetworkinventory();
             foreach ($targets as $keyt => $target) {
                 $item_type = key($target);
                 $items_id = current($target);
                 if ($item_type == 'PluginFusioninventoryIPRange') {
                     unset($targets[$keyt]);
                     // In this case get devices of this iprange
                     $deviceList = $pfNetworkinventory->getDevicesOfIPRange($items_id);
                     $targets = array_merge($targets, $deviceList);
                 }
             }
         }
         foreach ($targets as $target) {
             $item_type = key($target);
             $item_id = current($target);
             $target_id = $item_type . "_" . $item_id;
             if (isset($targets_cache[$target_id])) {
                 $item = $targets_cache[$target_id];
             } else {
                 $item = new $item_type();
                 $item->getFromDB($item_id);
                 $targets_cache[$target_id] = $item;
             }
             $targets_handle[$target_id] = array('id' => $item->fields['id'], 'name' => $item->fields['name'], 'type_name' => $item->getTypeName(), 'item_link' => $item->getLinkUrl(), 'counters' => array(), 'agents' => array());
             // create agent states counter lists
             foreach ($agent_state_types as $type) {
                 $targets_handle[$target_id]['counters'][$type] = array();
             }
         }
     }
     // Query fields mapping used to easily select fields by name
     $query_fields = array(array('task.id', 'task.`id`'), array('task.name', 'task.`name`'), array('job.id', 'job.`id`'), array('job.name', 'job.`name`'), array('job.method', 'job.`method`'), array('agent.id', 'agent.`id`'), array('agent.name', 'agent.`name`'), array('run.id', 'run.`id`'), array('run.itemtype', 'run.`itemtype`'), array('run.items_id', 'run.`items_id`'), array('run.state', 'run.`state`'), array('log.last_date', 'log.`date`'), array('log.last_timestamp', 'UNIX_TIMESTAMP(log.`date`)'), array('log.last_id', 'log.`id`'), array('log.last_comment', 'log.`comment`'));
     $fieldmap = array();
     foreach ($query_fields as $index => $key) {
         $fieldmap[$key[0]] = $index;
     }
     $query_select = array();
     foreach ($query_fields as $index => $key) {
         $query_select[] = $key[1] . " AS '" . $key[0] . "'";
     }
     $query_joins = array();
     $query_joins['max_run'] = implode("\n", array("INNER JOIN (", "  SELECT", "     MAX(run.`id`) AS max_id,", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`,", "     MAX(log.`id`) AS max_log_id", "  FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", "  LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", "  ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", "  GROUP BY", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`"));
     $query_joins['run'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobstates` AS run", "  ON max_run.`max_id` = run.`id`"));
     $query_joins['log'] = implode("\n", array("LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` as log", "  ON log.`id` = max_run.`max_log_id`"));
     $query_joins['job'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_taskjobs` AS job", "  ON job.`id` = run.`plugin_fusioninventory_taskjobs_id`"));
     $query_joins['task'] = implode("\n", array("INNER JOIN `glpi_plugin_fusioninventory_tasks` as task", "  ON job.`plugin_fusioninventory_tasks_id` = task.`id`"));
     $queries = array();
     /*
      * Get latest jobstates for agents
      */
     $queries['1_last_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null);
     /*
      * Get last finished jobstates (ie. `state` >= 3)
      */
     $query_joins['max_run'] = implode("\n", array("INNER JOIN (", "  SELECT", "     MAX(run.`id`) AS max_id,", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`,", "     MAX(log.`id`) AS max_log_id", "  FROM `glpi_plugin_fusioninventory_taskjobstates` AS run", "  LEFT JOIN `glpi_plugin_fusioninventory_taskjoblogs` AS log", "  ON log.`plugin_fusioninventory_taskjobstates_id` = run.`id`", "  WHERE run.`state` IN ( " . implode(",", array(PluginFusioninventoryTaskjobstate::FINISHED, PluginFusioninventoryTaskjobstate::IN_ERROR)) . " )", "  GROUP BY", "     run.`plugin_fusioninventory_agents_id`,", "     run.`plugin_fusioninventory_taskjobs_id`,", "     run.`items_id`, run.`itemtype`", ") max_run ON max_run.`plugin_fusioninventory_agents_id` = agent.`id`"));
     $queries['2_finished_runs'] = array('query' => implode(" \n", array("SELECT", implode(",\n", $query_select), "FROM `glpi_plugin_fusioninventory_agents` AS agent", implode("\n", $query_joins), implode("\n", $query_where), "GROUP BY job.`id`, agent.`id`, run.`id`")), 'result' => null);
     $query_chrono = array("start" => microtime(true), "end" => 0);
     ksort($queries);
     foreach ($queries as $query_name => $contents) {
         $queries[$query_name]['result'] = $DB->query($contents['query']);
         $query_chrono['end'] = microtime(true);
         // For debug only
         //if ($debug_mode) {
         //   file_put_contents("/tmp/glpi_".$query_name.".sql",$contents['query']);
         //}
     }
     $agents = array();
     $format_chrono = array("start" => microtime(true), "end" => 0);
     foreach ($queries as $query_name => $contents) {
         if (!is_null($contents['result'])) {
             while ($result = $contents['result']->fetch_row()) {
                 // We need to check if the results are consistent with the view's structure gathered
                 // by the first query
                 $task_id = $result[$fieldmap['task.id']];
                 //if (!array_key_exists($task_id, $logs)) {
                 if (!isset($logs[$task_id])) {
                     continue;
                 }
                 $job_id = $result[$fieldmap['job.id']];
                 $jobs =& $logs[$task_id]['jobs'];
                 if (!isset($jobs[$job_id])) {
                     continue;
                 }
                 $target_id = $result[$fieldmap['run.itemtype']] . '_' . $result[$fieldmap['run.items_id']];
                 $targets =& $jobs[$job_id]['targets'];
                 if (!isset($targets[$target_id])) {
                     continue;
                 }
                 $counters =& $targets[$target_id]['counters'];
                 $agent_id = $result[$fieldmap['agent.id']];
                 $agents[$agent_id] = $result[$fieldmap['agent.name']];
                 if (!isset($targets[$target_id]['agents'][$agent_id])) {
                     $targets[$target_id]['agents'][$agent_id] = array();
                 }
                 $agent_state = '';
                 // Update counters
                 switch ($result[$fieldmap['run.state']]) {
                     case PluginFusioninventoryTaskjobstate::CANCELLED:
                         // We put this agent in the cancelled counter if it does not have any other job
                         // states.
                         if (!isset($counters['agents_prepared'][$agent_id]) and !isset($counters['agents_running'][$agent_id])) {
                             $counters['agents_cancelled'][$agent_id] = 1;
                             $agent_state = 'cancelled';
                         }
                         break;
                     case PluginFusioninventoryTaskjobstate::PREPARED:
                         // We put this agent in the prepared counter if it has not yet completed any job.
                         $counters['agents_prepared'][$agent_id] = 1;
                         $agent_state = 'prepared';
                         break;
                     case PluginFusioninventoryTaskjobstate::SERVER_HAS_SENT_DATA:
                     case PluginFusioninventoryTaskjobstate::AGENT_HAS_SENT_DATA:
                         // This agent is running so it must not be in any other counter
                         foreach ($agent_state_types as $type) {
                             if (isset($counters[$type][$agent_id])) {
                                 unset($counters[$type][$agent_id]);
                             }
                         }
                         $counters['agents_running'][$agent_id] = 1;
                         $agent_state = 'running';
                         break;
                     case PluginFusioninventoryTaskjobstate::IN_ERROR:
                         if (isset($counters['agents_success'][$agent_id])) {
                             unset($counters['agents_success'][$agent_id]);
                         }
                         $counters['agents_error'][$agent_id] = 1;
                         $agent_state = 'error';
                         if (isset($counters['agents_notdone'][$agent_id])) {
                             unset($counters['agents_notdone'][$agent_id]);
                         }
                         break;
                     case PluginFusioninventoryTaskjobstate::FINISHED:
                         if (isset($counters['agents_error'][$agent_id])) {
                             unset($counters['agents_error'][$agent_id]);
                         }
                         $counters['agents_success'][$agent_id] = 1;
                         $agent_state = 'success';
                         if (isset($counters['agents_notdone'][$agent_id])) {
                             unset($counters['agents_notdone'][$agent_id]);
                         }
                         break;
                 }
                 if (!isset($counters['agents_error'][$agent_id]) and !isset($counters['agents_success'][$agent_id])) {
                     $counters['agents_notdone'][$agent_id] = 1;
                 }
                 if (isset($counters['agents_running'][$agent_id]) or isset($counters['agents_prepared'][$agent_id])) {
                     unset($counters['agents_cancelled'][$agent_id]);
                 }
                 $targets[$target_id]['agents'][$agent_id][] = array('agent_id' => $agent_id, 'numstate' => $result[$fieldmap['run.state']], 'state' => $agent_state, 'jobstate_id' => $result[$fieldmap['run.id']], 'last_log_id' => $result[$fieldmap['log.last_id']], 'last_log_date' => $result[$fieldmap['log.last_date']], 'timestamp' => $result[$fieldmap['log.last_timestamp']], 'last_log' => $result[$fieldmap['log.last_comment']]);
             }
         }
     }
     $format_chrono['end'] = microtime(true);
     if ($debug_mode) {
         function tmp_display_log($log)
         {
             return "ID:" . $log['task_id'] . "(" . $log['task_name'] . ")";
         }
         if (PluginFusioninventoryConfig::isExtradebugActive()) {
             Toolbox::logDebug(array("tasks" => implode(',', array_map('tmp_display_log', $logs)), "row count" => count($logs), "Joblogs Query" => self::FormatChrono($query_chrono), "Format logs results" => self::FormatChrono($format_chrono)));
         }
     }
     return array('tasks' => $logs, 'agents' => $agents);
 }