<?php
//API Credentials and Export Location
$cxalloy_identifier = '';
$cxalloy_secret     = '';
$cxalloy_projects   = [
	'Project Name' 	=> 1234
];

ini_set('memory_limit', '1G');

$results = api_test($cxalloy_projects, $cxalloy_identifier, $cxalloy_secret);
var_dump($results);

/**
 *  Function to retrieve project data for subsequent .csv file generation.
 *
 * @param string $project - The ID of the project to export.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API secret key.
 *
 * @return array - Output array to feed into fputcsv function.
 */
function api_test($projects, $identifier, $secret)
{
	$data = [];

	$sections = [
		'equipment',
		'types',
		'systems',
		'spaces',
		'floors',
		'zones',
		'buildings',
		'campuses',
		'issues',
		'checklists',
		'tests'
	];

	foreach ($projects as $name => $project)
	{
		$data[$name] = [];

		foreach ($sections as $section)
		{
			$get_function = 'get_' . $section;
			$format_function = 'format_' . $section;
			$items = $get_function($project, $identifier, $secret);
			$data[$name][$section] = $format_function($project, $items, $identifier, $secret);

			//Can pass desired filename/directory as second parameter
			//e.g. export_equipment($data['equipment'], 'filepath/filename')
			//don't include extension in filename, .csv is appended automatically
			export_items($data[$name][$section], $project . '_' . $section . '_export');
		}
	}

	return $data;
}

/**
 *  Helper function to set include options prior to type get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_types($project, $identifier, $secret, $id = NULL)
{
	$includes = [

	];

	return get('equipmenttype', $project, $identifier, $secret, $includes, $id);
}

/**
 *  Helper function to set include options prior to system get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_systems($project, $identifier, $secret, $id = NULL)
{
	$includes = [
		'attributes'
	];

	return get('system', $project, $identifier, $secret, $includes, $id);
}

/**
 *  Helper function to set include options prior to space get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_spaces($project, $identifier, $secret)
{
	$includes = [

	];

	return get('space', $project, $identifier, $secret, $includes);
}

/**
 *  Helper function to set include options prior to floor get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_floors($project, $identifier, $secret)
{
	$includes = [

	];

	return get('floor', $project, $identifier, $secret, $includes);
}

/**
 *  Helper function to set include options prior to zone get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_zones($project, $identifier, $secret)
{
	$includes = [

	];

	return get('zone', $project, $identifier, $secret, $includes);
}

/**
 *  Helper function to set include options prior to building get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_buildings($project, $identifier, $secret)
{
	$includes = [

	];

	return get('building', $project, $identifier, $secret, $includes);
}

/**
 *  Helper function to set include options prior to campus get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_campuses($project, $identifier, $secret)
{
	$includes = [

	];

	return get('campus', $project, $identifier, $secret, $includes);
}

/**
 *  Helper function to set include options prior to equipment get request
 *
 * @return object - The results returned by the cURL request.
 */
function get_equipment($project, $identifier, $secret, $id = NULL)
{
	$includes = [
		'systems',
		'zones',
		'areas_served',
		'attributes',
		'time_to_close',
		'extended_status'
	];

	return get('equipment', $project, $identifier, $secret, $includes, $id);
}

/**
 *  Helper function to get checklist data
 *
 * @param string $project - The ID of the project to get data from.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API key secret.
 * @param int $page - (Optional) The page to request; defaults to 1.
 *
 * @return object - The results returned by the checklist cURL request.
 */
function get_issues($project, $identifier, $secret, $page = 1)
{
	$endpoint = 'issue';
	$timestamp = time();
	$type = 'POST';
	$filters = [];

	$includes = [
		'comments',
		'time_to_close',
		'extended_status'
	];

	$body = [
		'project_id' => $project,
		'filter'=>$filters,
		'page'=>$page,
		'include'=>$includes
	];

	$items = send_cx_request($endpoint, $timestamp, $identifier, $secret, $type, $body);

	if ( ! empty($items->records))
	{
		$items = $items->records;

		if (count($items) === 500)
		{
			$items = (object) array_merge((array) $items, (array) get_issues($project, $identifier, $secret, $page + 1));
		}
	}

	return $items;
}

/**
 *  Helper function to get checklist data
 *
 * @param string $project - The ID of the project to get data from.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API key secret.
 * @param int $page - (Optional) The page to request; defaults to 1.
 *
 * @return object - The results returned by the checklist cURL request.
 */
function get_checklists($project, $identifier, $secret, $page = 1)
{
	$endpoint = 'checklist';
	$timestamp = time();
	$type = 'POST';
	$filters = [];

	$includes = [
		'lines',
		'time_to_close',
		'extended_status'
	];

	$body = [
		'project_id' => $project,
		'filter' => $filters,
		'page' => $page,
		'include' => $includes
	];

	$items = send_cx_request($endpoint, $timestamp, $identifier, $secret, $type, $body);

	if ( ! empty($items->records))
	{
		$items = $items->records;

		if (count($items) === 500)
		{
			$items = (object) array_merge((array) $items, (array) get_checklists($project, $identifier, $secret, $page + 1));
		}
	}

	return $items;
}


/**
 *  Helper function to get test data
 *
 * @param string $project - The ID of the project to get data from.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API key secret.
 * @param int $page - (Optional) The page to request; defaults to 1.
 *
 * @return object - The results returned by the checklist cURL request.
 */
function get_tests($project, $identifier, $secret, $page = 1)
{
	$endpoint = 'test';
	$timestamp = time();
	$type = 'POST';
	$filters = [];

	$includes = [
		'attempts',
		'lines',
		'time_to_close',
		'extended_status'
	];

	$body = [
		'project_id' => $project,
		'filter' => $filters,
		'page' => $page,
		'include' => $includes
	];

	$items = send_cx_request($endpoint, $timestamp, $identifier, $secret, $type, $body);

	if ( ! empty($items->records))
	{
		$items = $items->records;

		if (count($items) === 500)
		{
			$items = (object) array_merge((array) $items, (array) get_tests($project, $identifier, $secret, $page + 1));
		}
	}

	return $items;
}

/**
 *  Helper function to format equipment data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $equipment - The object from the equipment cURL request.
 *
 * @return array - The formatted equipment data array.
 */
function format_equipment($project, $equipment, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Status',
		'Description',
		'Type',
		'Systems',
		'Discipline',
		'Space',
		'Floor',
		'Building',
		'Zones',
		'Areas Served',
		'Notes',
		'Link',
		'Time to Close'
	];

	$x = 0;

	if ( ! empty($equipment))
	{
		foreach ($equipment as $asset)
		{
			if ( ! empty($asset->name))
			{
				$data[$x][0] = $asset->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($asset->status))
			{
				$data[$x][1] = $asset->status;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($asset->description))
			{
				$data[$x][2] = $asset->description;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($asset->type))
			{
				$data[$x][3] = $asset->type;
			}
			else
			{
				$data[$x][3] = '';
			}

			if ( ! empty($asset->systems))
			{
				// name, description, building, discipline
				$data[$x][4] = '';
				$i = 1;
				$count = count($asset->systems);
				foreach ($asset->systems as $system)
				{
					$data[$x][4] .= $system->name;
					if ($i !== $count)
					{
						$data[$x][4] .= ' | ';
					}
				}
			}
			else
			{
				$data[$x][4] = '';
			}

			if ( ! empty($asset->discipline))
			{
				$data[$x][5] = $asset->discipline;
			}
			else
			{
				$data[$x][5] = '';
			}

			if ( ! empty($asset->space))
			{
				$data[$x][6] = $asset->space;
			}
			else
			{
				$data[$x][6] = '';
			}

			if ( ! empty($asset->floor))
			{
				$data[$x][7] = $asset->floor;
			}
			else
			{
				$data[$x][7] = '';
			}

			if ( ! empty($asset->building))
			{
				$data[$x][8] = $asset->building;
			}
			else
			{
				$data[$x][8] = '';
			}

			if ( ! empty($asset->zone))
			{
				$data[$x][9] = $asset->zone;
			}
			else
			{
				$data[$x][9] = '';
			}

			if ( ! empty($asset->areas_served))
			{
				//area_served_name, area_served_type, area_served_id
				$data[$x][10] = '';
				$i = 1;
				$count = count($asset->areas_served);
        foreach ($asset->areas_served as $area)
        {
					$data[$x][10] .= $area->area_served_name;
					if ($i !== $count)
					{
						$data[$x][10] .= ' | ';
					}
        }
			}
			else
			{
				$data[$x][10] = '';
			}

			if ( ! empty($asset->notes))
			{
				$data[$x][11] = $asset->notes;
			}
			else
			{
				$data[$x][11] = '';
			}

			$data[$x][12] = 'https://tq.cxalloy.com/project/' . $project . '/equipment/' . $asset->equipment_id;

			if ( ! empty($asset->time_to_close_seconds))
			{
				$data[$x][13] = $asset->time_to_close_seconds;
			}
			else
			{
				$data[$x][13] = '';
			}

			$status_columns = 0;
			if ( ! empty($asset->extended_status))
			{
				foreach ($asset->extended_status as $column_name => $status_info)
				{
					if ( ! in_array($column_name, $data['Headers']))
					{
						$data['Headers'][] = $column_name;
					}

					$key = array_search($column_name, $data['Headers']);
					$data[$x][$key] = $status_info;

					if (str_ends_with($column_name, '_person'))
					{
						$date_column = str_replace('_person','_date',$column_name);
						$latest_date_column = 'latest_' . $date_column;
						$latest_person_column = 'latest_' . $column_name;

						if ( ! in_array($latest_date_column, $data['Headers']))
						{
							$data['Headers'][] = $latest_date_column;
							$data['Headers'][] = $latest_person_column;
						}

						$dates = explode("\n", $asset->extended_status->$date_column);
						$latest = '';

						$i = 0;
						foreach ($dates as $index => $date)
						{
							if ($date > $latest)
							{
								$latest = $date;
								$i = $index;
							}
						}

						$key = array_search($latest_date_column, $data['Headers']);
						$data[$x][$key] = $latest;
						$people = explode("\n", $status_info);
						$key = array_search($latest_person_column, $data['Headers']);
						$data[$x][$key] = $people[$i];

						$status_columns = $status_columns + 2;
					}

					$status_columns++;
				}
			}

			for ($i = 14 + $status_columns; $i < count($data['Headers']); $i++)
			{
				if (empty($data[$x][$i]))
				{
					$data[$x][$i] = '';
				}
			}

			if ( ! empty($asset->attributes))
			{
				foreach($asset->attributes as $attribute)
				{
					if ( ! in_array($attribute->name, $data['Headers']))
					{
						$data['Headers'][] = $attribute->name;
						if ( ! empty($attribute->unit))
						{
							$data['Headers'][] = $attribute->name . ' Units ' . '(' . $attribute->unit . ')';
						}
					}

					$key = array_search($attribute->name, $data['Headers']);
					$data[$x][$key] = $attribute->value;

					if (array_key_exists($key + 1, $data['Headers']) && ($data['Headers'][$key + 1] === ($attribute->name . ' Units ' . '(' . $attribute->unit . ')')))
					{
						$data[$x][$key + 1] = $attribute->unit;
					}
				}
			}

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_types($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Discipline',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->discipline))
			{
				$data[$x][2] = $item->discipline;
			}
			else
			{
				$data[$x][2] = '';
			}

			$data[$x][3] = 'https://tq.cxalloy.com/project/' . $project . '/equipmenttype#' . $item->equipmenttype_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_systems($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Discipline',
		'Building',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->discipline))
			{
				$data[$x][2] = $item->discipline;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($item->building))
			{
				$data[$x][3] = $item->building;
			}
			else
			{
				$data[$x][3] = '';
			}

			$data[$x][4] = 'https://tq.cxalloy.com/project/' . $project . '/system#' . $item->system_id;

			for ($i = 5; $i < count($data['Headers']); $i++)
			{
				if (empty($data[$x][$i]))
				{
					$data[$x][$i] = '';
				}
			}

			if ( ! empty($item->attributes))
			{
				foreach($item->attributes as $attribute)
				{
					if ( ! in_array($attribute->name, $data['Headers']))
					{
						$data['Headers'][] = $attribute->name;
						if ( ! empty($attribute->unit))
						{
							$data['Headers'][] = $attribute->name . ' Units ' . '(' . $attribute->unit . ')';
						}
					}

					$key = array_search($attribute->name, $data['Headers']);

					$data[$x][$key] = $attribute->value;
					if (array_key_exists($key + 1, $data['Headers']) && ($data['Headers'][$key + 1] === ($attribute->name . ' Units ' . '(' . $attribute->unit . ')')))
					{
						$data[$x][$key + 1] = $attribute->unit;
					}
				}
			}

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_spaces($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Floor',
		'Building',
		'Campus',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->floor))
			{
				$data[$x][2] = $item->floor;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($item->building))
			{
				$data[$x][3] = $item->building;
			}
			else
			{
				$data[$x][3] = '';
			}

			if ( ! empty($item->campus))
			{
				$data[$x][4] = $item->campus;
			}
			else
			{
				$data[$x][4] = '';
			}

			$data[$x][5] = 'https://tq.cxalloy.com/project/' . $project . '/location#space-' . $item->space_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_floors($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Building',
		'Campus',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->building))
			{
				$data[$x][2] = $item->building;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($item->campus))
			{
				$data[$x][3] = $item->campus;
			}
			else
			{
				$data[$x][3] = '';
			}

			$data[$x][4] = 'https://tq.cxalloy.com/project/' . $project . '/location#floor-' . $item->floor_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_zones($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Building',
		'Campus',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->building))
			{
				$data[$x][2] = $item->building;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($item->campus))
			{
				$data[$x][3] = $item->campus;
			}
			else
			{
				$data[$x][3] = '';
			}

			$data[$x][4] = 'https://tq.cxalloy.com/project/' . $project . '/location#zone-' . $item->zone_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_buildings($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Campus',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->campus))
			{
				$data[$x][2] = $item->campus;
			}
			else
			{
				$data[$x][2] = '';
			}

			$data[$x][3] = 'https://tq.cxalloy.com/project/' . $project . '/location#building-' . $item->building_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_campuses($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Link'
	];
	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			$data[$x][2] = 'https://tq.cxalloy.com/project/' . $project . '/location#campus-' . $item->campus_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $items - The object from the cURL request.
 *
 * @return array - The formatted data array.
 */
function format_issues($project, $items, $identifier, $secret)
{
	$data['Headers'] = [
		'Name',
		'Description',
		'Asset',
		'Asset Type',
		'Equipment Type',
		'System',
		'Drawing',
		'Priority',
		'Due Date',
		'Assigned To',
		'Discipline',
		'Status',
		'Comments',
		'Source',
		'Date Closed',
		'Created By',
		'Date Created',
		'Link',
		'Time to Close'
	];

	$x = 0;

	if ( ! empty($items))
	{
		foreach ($items as $item)
		{
			if ( ! empty($item->name))
			{
				$data[$x][0] = $item->name;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($item->description))
			{
				$data[$x][1] = $item->description;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($item->asset_name))
			{
				$data[$x][2] = $item->asset_name;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($item->asset_type))
			{
				$data[$x][3] = $item->asset_type;

				if ( $item->asset_type === 'Equipment')
				{
					$equipment = $this->get_equipment($project, $identifier, $secret, $item->asset_key);
					$data[$x][4] = $equipment->type;

					if ( ! empty($equipment->systems))
					{
						//area_served_name, area_served_type, area_served_id
						$data[$x][5] = '';
						$i = 1;
						$count = count($equipment->systems);
						foreach ($equipment->systems as $system)
						{
							$data[$x][5] .= $system->system_name;
							if ($i !== $count)
							{
								$data[$x][5] .= ' | ';
							}
						}
					}
					else
					{
						$data[$x][5] = '';
					}
				}
				else
				{
					$data[$x][4] = '';
					$data[$x][5] = '';
				}
			}
			else
			{
				$data[$x][3] = '';
				$data[$x][4] = '';
				$data[$x][5] = '';
			}

			if ( ! empty($item->drawing))
			{
				$data[$x][6] = $item->drawing;
			}
			else
			{
				$data[$x][6] = '';
			}

			if ( ! empty($item->priority))
			{
				$data[$x][7] = $item->priority;
			}
			else
			{
				$data[$x][7] = '';
			}

			if ( ! empty($item->due_date))
			{
				$data[$x][8] = $item->due_date;
			}
			else
			{
				$data[$x][8] = '';
			}

			if ( ! empty($item->assigned_name))
			{
				$data[$x][9] = $item->assigned_name;
			}
			else
			{
				$data[$x][9] = '';
			}

			if ( ! empty($item->discipline))
			{
				$data[$x][10] = $item->discipline;
			}
			else
			{
				$data[$x][10] = '';
			}

			if ( ! empty($item->status))
			{
				$data[$x][11] = $item->status;
			}
			else
			{
				$data[$x][11] = '';
			}

			if ( ! empty($item->comments))
			{
				// comment, created_name, date_created
				$data[$x][12] = '';
				$i = 1;
				$count = count($item->comments);
				foreach ($item->comments as $comment)
				{
					$data[$x][12] .= $comment->comment . ' - ' . $comment->created_name . ', ' . $comment->date_created;
					if ($i !== $count)
					{
						$data[$x][12] .= ' | ';
					}
				}
			}
			else
			{
				$data[$x][12] = '';
			}

			if ( ! empty($item->source_type) && ! empty($item->source_name))
			{
				$data[$x][13] = $item->source_type . ' ' . $item->source_name;
			}
			else
			{
				$data[$x][13] = '';
			}

			if ( ! empty($item->date_closed))
			{
				$data[$x][14] = $item->date_closed;
			}
			else
			{
				$data[$x][14] = '';
			}

			if ( ! empty($item->created_by))
			{
				$data[$x][15] = $item->created_by;
			}
			else
			{
				$data[$x][15] = '';
			}

			if ( ! empty($item->date_created))
			{
				$data[$x][16] = $item->date_created;
			}
			else
			{
				$data[$x][16] = '';
			}

			$data[$x][17] = 'https://tq.cxalloy.com/project/' . $project . '/' . $item->section . 'issue/' . $item->issue_id;

			if ( ! empty($item->time_to_close_seconds))
			{
				$data[$x][18] = $item->time_to_close_seconds;
			}
			else
			{
				$data[$x][18] = '';
			}

			$status_columns = 0;
			if ( ! empty($item->extended_status))
			{
				foreach ($item->extended_status as $column_name => $status_info)
				{
					if ( ! in_array($column_name, $data['Headers']))
					{
						$data['Headers'][] = $column_name;
					}

					$key = array_search($column_name, $data['Headers']);
					$data[$x][$key] = $status_info;

					if (str_ends_with($column_name, '_person'))
					{
						$date_column = str_replace('_person','_date',$column_name);
						$latest_date_column = 'latest_' . $date_column;
						$latest_person_column = 'latest_' . $column_name;

						if ( ! in_array($latest_date_column, $data['Headers']))
						{
							$data['Headers'][] = $latest_date_column;
							$data['Headers'][] = $latest_person_column;
						}

						$dates = explode("\n", $item->extended_status->$date_column);
						$latest = '';

						$i = 0;
						foreach ($dates as $index => $date)
						{
							if ($date > $latest)
							{
								$latest = $date;
								$i = $index;
							}
						}

						$key = array_search($latest_date_column, $data['Headers']);
						$data[$x][$key] = $latest;
						$people = explode("\n", $status_info);
						$key = array_search($latest_person_column, $data['Headers']);
						$data[$x][$key] = $people[$i];

						$status_columns = $status_columns + 2;
					}

					$status_columns++;
				}
			}

			for ($i = 19 + $status_columns; $i < count($data['Headers']); $i++)
			{
				if (empty($data[$x][$i]))
				{
					$data[$x][$i] = '';
				}
			}

			if ( ! empty($item->attributes))
			{
				foreach($item->attributes as $attribute)
				{
					if ( ! in_array($attribute->name, $data['Headers']))
					{
						$data['Headers'][] = $attribute->name;
						if ( ! empty($attribute->unit))
						{
							$data['Headers'][] = $attribute->name . ' Units ' . '(' . $attribute->unit . ')';
						}
					}

					$key = array_search($attribute->name, $data['Headers']);
					$data[$x][$key] = $attribute->value;

					if (array_key_exists($key + 1, $data['Headers']) && ($data['Headers'][$key + 1] === ($attribute->name . ' Units ' . '(' . $attribute->unit . ')')))
					{
						$data[$x][$key + 1] = $attribute->unit;
					}
				}
			}

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format checklist data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $checklists - The object from the checklist cURL request.
 *
 * @return array - The formatted checklist data array.
 */
function format_checklists($project, $checklists, $identifier, $secret)
{
	$data['Headers'] = [
		'Number',
		'Name',
		'Status',
		'Yes (%)',
		'No (%)',
		'NA (%)',
		'Note',
		'Type',
		'Asset',
		'Asset Type',
		'Tools',
		'Assigned To',
		'Link',
		'Time to Close'
	];
	$x = 0;

	if ( ! empty($checklists))
	{
		foreach ($checklists as $checklist)
		{
			if ( ! empty($checklist->number))
			{
				$data[$x][0] = $checklist->number;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($checklist->name))
			{
				$data[$x][1] = $checklist->name;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($checklist->status))
			{
				$data[$x][2] = $checklist->status;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($checklist->lines))
			{
				$total = 0;
				$num_yes = 0;
				$num_no = 0;
				$num_na = 0;

				foreach ($checklist->lines as $line)
				{
					if (is_numeric($line->line_number))
					{
						$total++;

						if ($line->answer === 'yes')
						{
							$num_yes++;
						}
						elseif ($line->answer === 'no')
						{
							$num_no++;
						}
						elseif ($line->answer === 'na')
						{
							$num_na++;
						}
					}
				}

				$data[$x][3] = sprintf("%.2f%%", $num_yes / $total * 100);
				$data[$x][4] = sprintf("%.2f%%", $num_no / $total * 100);
				$data[$x][5] = sprintf("%.2f%%", $num_na / $total * 100);
			}
			else
			{
				$data[$x][3] = 'No Lines';
				$data[$x][4] = 'No Lines';
				$data[$x][5] = 'No Lines';
			}

			if ( ! empty($checklist->note))
			{
				$data[$x][6] = $checklist->note;
			}
			else
			{
				$data[$x][6] = '';
			}

			if ( ! empty($checklist->type_name))
			{
				$data[$x][7] = $checklist->type_name;
			}
			else
			{
				$data[$x][7] = '';
			}

			if ( ! empty($checklist->asset_name))
			{
				$data[$x][8] = $checklist->asset_name;
			}
			else
			{
				$data[$x][8] = '';
			}

			if ( ! empty($checklist->asset_type))
			{
				$data[$x][9] = $checklist->asset_type;
			}
			else
			{
				$data[$x][9] = '';
			}

			if ( ! empty($checklist->tools))
			{
				$data[$x][10] = $checklist->tools;
			}
			else
			{
				$data[$x][10] = '';
			}

			if ( ! empty($checklist->assigned_name))
			{
				$data[$x][11] = $checklist->assigned_name;
			}
			else
			{
				$data[$x][11] = '';
			}

			$data[$x][12] = 'https://tq.cxalloy.com/project/' . $project . '/checklists/' . $checklist->checklist_id;

			if ( ! empty($checklist->time_to_close_seconds))
			{
				$data[$x][13] = $checklist->time_to_close_seconds;
			}
			else
			{
				$data[$x][13] = '';
			}

			$status_columns = 0;
			if ( ! empty($checklist->extended_status))
			{
				foreach ($checklist->extended_status as $column_name => $status_info)
				{
					if ( ! in_array($column_name, $data['Headers']))
					{
						$data['Headers'][] = $column_name;
					}

					$key = array_search($column_name, $data['Headers']);
					$data[$x][$key] = $status_info;

					if (str_ends_with($column_name, '_person'))
					{
						$date_column = str_replace('_person','_date',$column_name);
						$latest_date_column = 'latest_' . $date_column;
						$latest_person_column = 'latest_' . $column_name;

						if ( ! in_array($latest_date_column, $data['Headers']))
						{
							$data['Headers'][] = $latest_date_column;
							$data['Headers'][] = $latest_person_column;
						}

						$dates = explode("\n", $checklist->extended_status->$date_column);
						$latest = '';

						$i = 0;
						foreach ($dates as $index => $date)
						{
							if ($date > $latest)
							{
								$latest = $date;
								$i = $index;
							}
						}

						$key = array_search($latest_date_column, $data['Headers']);
						$data[$x][$key] = $latest;
						$people = explode("\n", $status_info);
						$key = array_search($latest_person_column, $data['Headers']);
						$data[$x][$key] = $people[$i];

						$status_columns = $status_columns + 2;
					}

					$status_columns++;
				}
			}

			for ($i = 14 + $status_columns; $i < count($data['Headers']); $i++)
			{
				if (empty($data[$x][$i]))
				{
					$data[$x][$i] = '';
				}
			}

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to format test data from cURL request
 *
 * @param string $project - The ID of the project to get data from.
 * @param object $tests - The object from the checklist cURL request.
 *
 * @return array - The formatted checklist data array.
 */
function format_tests($project, $tests, $identifier, $secret)
{
	$data['Headers'] = [
		'Number',
		'Name',
		'Status',
		'Yes (%)',
		'No (%)',
		'NA (%)',
		'Note',
		'Asset',
		'Asset Type',
		'Tools',
		'Assigned To',
		'Link',
		'Time to Close'
	];
	$x = 0;

	if ( ! empty($tests))
	{
		foreach ($tests as $test)
		{
			if ( ! empty($test->number))
			{
				$data[$x][0] = $test->number;
			}
			else
			{
				$data[$x][0] = '';
			}

			if ( ! empty($test->name))
			{
				$data[$x][1] = $test->name;
			}
			else
			{
				$data[$x][1] = '';
			}

			if ( ! empty($test->status))
			{
				$data[$x][2] = $test->status;
			}
			else
			{
				$data[$x][2] = '';
			}

			if ( ! empty($test->attempts))
			{
				foreach ($test->attempts as $attempt)
				{
					if ( ! empty($attempt->lines))
					{
						$total = 0;
						$num_yes = 0;
						$num_no = 0;
						$num_na = 0;

						foreach ($attempt->lines as $line)
						{
							if (is_numeric($line->line_number))
							{
								$total++;

								if ($line->answer === 'yes')
								{
									$num_yes++;
								}
								elseif ($line->answer === 'no')
								{
									$num_no++;
								}
								elseif ($line->answer === 'na')
								{
									$num_na++;
								}
							}
						}

						$data[$x][3] = sprintf("%.2f%%", $num_yes / $total * 100);
						$data[$x][4] = sprintf("%.2f%%", $num_no / $total * 100);
						$data[$x][5] = sprintf("%.2f%%", $num_na / $total * 100);
					}
					else
					{
						$data[$x][3] = 'No Lines';
						$data[$x][4] = 'No Lines';
						$data[$x][5] = 'No Lines';
					}
				}
			}
			else
			{
				$data[$x][3] = 'No Attempts';
				$data[$x][4] = 'No Attempts';
				$data[$x][5] = 'No Attempts';
			}

			if ( ! empty($test->note))
			{
				$data[$x][6] = $test->note;
			}
			else
			{
				$data[$x][6] = '';
			}

			if ( ! empty($test->asset_name))
			{
				$data[$x][7] = $test->asset_name;
			}
			else
			{
				$data[$x][7] = '';
			}

			if ( ! empty($test->asset_type))
			{
				$data[$x][8] = $test->asset_type;
			}
			else
			{
				$data[$x][8] = '';
			}

			if ( ! empty($test->tools))
			{
				$data[$x][9] = $test->tools;
			}
			else
			{
				$data[$x][9] = '';
			}

			if ( ! empty($test->assigned_name))
			{
				$data[$x][10] = $test->assigned_name;
			}
			else
			{
				$data[$x][10] = '';
			}

			$data[$x][11] = 'https://tq.cxalloy.com/project/' . $project . '/tests/' . $test->test_id;

			$x++;
		}
	}

	$data['Rows'] = $x;

	return $data;
}

/**
 *  Helper function to build generic get request
 *
 * @param string $project - The ID of the project to get data from.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API key secret.
 * @param int $page - (Optional) The page to request; defaults to 1.
 *
 * @return object - The results returned by the checklists cURL request.
 */
function get($endpoint, $project, $identifier, $secret, $includes = [], $id = NULL, $page = 1)
{
	$uri = $endpoint;
	if ( ! empty($id))
	{
		 $uri .= '/' . $id;
	}
	$uri .= '?project_id=' . $project;

	if ( ! empty($includes))
	{
		$uri .= '&include=';
		$num_includes = count($includes);

		foreach ($includes as $include)
		{
			$uri .= $include;

			$num_includes--;
			if ($num_includes !== 0)
			{
				$uri .= ',';
			}
		}
	}

	$uri .= '&page=' . $page;
	$timestamp = time();
	$type = 'GET';

	$items = send_cx_request($uri, $timestamp, $identifier, $secret);

	if ( ! empty($items))
	{
		if (count($items) === 500)
		{
			$items = (object) array_merge((array) $items, (array) get($endpoint, $project, $identifier, $secret, $includes, NULL, $page + 1));
		}
	}

	return $items;
}

/**
 *  Function to generate .csv file
 *
 * @param array $items - The formatted data array.
 * @param string $filename - The desired name of the .csv file.
 *
 * @return void
 */
function export_items($items, $filename = 'item_export')
{
	$filename = __DIR__ . '/' . $filename . '.csv';

	$fp = fopen($filename, 'w');
	fputcsv($fp, $items['Headers']);

	$i = 0;
	while ($i < $items['Rows'])
	{
		fputcsv($fp, $items[$i]);
		$i++;
	}

	fclose($fp);
}

/**
 *  Function to make cURL request using CxAlloy authentication
 *
 * @param string $endpoint - The API endpoint to use, including any GET parameters.
 * @param string $timestamp - Unix timestamp to use to generate signature.
 * @param string $identifier - The API key identifier.
 * @param string $secret - The API key secret.
 * @param string $type - GET, POST, PUT, DELETE. Defaults to GET.
 * @param array $body - Endpoint options as an array. (optional)
 *
 * @return mixed
 */
function send_cx_request($endpoint, $timestamp, $identifier, $secret, $type = 'GET', $body = NULL)
{
		if (empty($timestamp))
		{
				return false;
		}

		// concat json encoded arguments with the timestamp from cxalloy-timestamp header
		if( ! empty($body))
		{
				$string = json_encode($body) . $timestamp;
		}
		else
		{
				$string = $timestamp;
		}

		//generate the signature
		$signature = hash_hmac('sha256', $string, $secret);

		$curl = curl_init();

		$base_url = 'https://tq.cxalloy.com/api/v1/';
		curl_setopt_array($curl, array(
			CURLOPT_URL => $base_url . $endpoint,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_ENCODING => "",
			CURLOPT_MAXREDIRS => 10,
			CURLOPT_TIMEOUT => 600,
			CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
			CURLOPT_CUSTOMREQUEST => $type,
			CURLOPT_HTTPHEADER => array(
				"cache-control: no-cache",
				"content-type: application/json",
				"cxalloy-identifier: $identifier",
				"cxalloy-signature: $signature",
				"cxalloy-timestamp: $timestamp",
				"user-agent: cxalloy-support-example"
			),
		));

		// add the request body if needed
		if ( ! empty($body) && $type !== 'GET')
		{
			curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));
		}

    $result = curl_exec($curl);

    curl_close($curl);

    $response = json_decode($result);

    return $response;
}
