/*********************************************
* Creates a backlog item in the project with the specified name, under the parent object (if not empty string).
* The items will be called the item name.
* Params:
*	projectName - name of the project to create the item in the backlog
*	parentName - name of the parent item to put the item under
*	itemName - name for the newly created item
* Returns:
*  the ref ID of the newly created item. -1 if not successful.
**********************************************/
HPMUniqueID HansoftUtils::createBacklogItem(HPMString projectName, HPMString parentName, HPMString itemName)
{
	HPMSdkSession *session = SessionManager::getInstance().Session();
	HPMUniqueID projectID = HansoftUtils::findProject(projectName);
	if (!projectID.IsValid())
		return -1;
	HPMProjectProperties projectProp = session->ProjectGetProperties(projectID);
	HPMUniqueID productBacklogUID = session->ProjectUtilGetBacklog(projectID);
	HPMTaskEnum Tasks = session->TaskEnum(productBacklogUID);
	for (HPMUInt32 j = 0; j < Tasks.m_Tasks.size(); ++j)
	{
		HPMUniqueID parentBacklogID = Tasks.m_Tasks[j];
		// TODO: Handle if no parent is specified
		if (session->TaskGetDescription(parentBacklogID).compare(parentName) == 0)
		{
			HPMTaskCreateUnified newBacklogItem;
			newBacklogItem.m_Tasks.resize(1);
			newBacklogItem.m_Tasks[0].m_bIsProxy = false;
			newBacklogItem.m_Tasks[0].m_LocalID = -1;
			newBacklogItem.m_Tasks[0].m_TaskLockedType = EHPMTaskLockedType_BacklogItem;

			HPMTaskCreateUnifiedReference prevRefID;
			prevRefID.m_bLocalID = false;
			prevRefID.m_RefID = -1;
			newBacklogItem.m_Tasks[0].m_PreviousRefID = prevRefID;

			HPMTaskCreateUnifiedReference prevWorkPrioRefID;
			prevWorkPrioRefID.m_bLocalID = false;
			prevWorkPrioRefID.m_RefID = -2;
			newBacklogItem.m_Tasks[0].m_PreviousWorkPrioRefID = prevWorkPrioRefID;

			HPMTaskCreateUnifiedReference parentBacklogTaskRefID;
			parentBacklogTaskRefID.m_bLocalID = false;
			parentBacklogTaskRefID.m_RefID = session->TaskGetMainReference(parentBacklogID);
			newBacklogItem.m_Tasks[0].m_ParentRefIDs.push_back(parentBacklogTaskRefID);

			newBacklogItem.m_Tasks[0].m_NonProxy_ReuseID = 0;
			newBacklogItem.m_Tasks[0].m_NonProxy_WorkflowID = 0xffffffff;

			HPMChangeCallbackData_TaskCreateUnified TaskCreateReturn = session->TaskCreateUnifiedBlock(productBacklogUID, newBacklogItem);
			if (newBacklogItem.m_Tasks.size() == 1)
			{
				// The returned is a task ref in the project container. We need the task id not the reference id.
				HPMUniqueID newTestSuiteTaskRefID = TaskCreateReturn.m_Tasks[0].m_TaskRefID;

				HPMUniqueID newTestSuiteTaskID = session->TaskRefGetTask(newTestSuiteTaskRefID);

				// Set the name and the status of the test suite
				session->TaskSetDescription(newTestSuiteTaskID, itemName);
				session->TaskSetStatus(newTestSuiteTaskID, EHPMTaskStatus_NotDone, true, EHPMTaskSetStatusFlag_All);

				session->TaskSetFullyCreated(newTestSuiteTaskID);
				return newTestSuiteTaskRefID;
			}
			else
				return -1;
		}
	}
	return -1;
}
/*********************************************
* Creates a new test cycle to commit selected test cases to
* Params:
*	name - the name of the new test cycle
*   duration - the number of days the cycle should last
*   projectUID - the id of the project to add the cycle in
* Returns:
*	The reference ID of the created sprint.
*********************************************/
HPMUniqueID HansoftUtils::createSprint(HPMString name, int duration, HPMUniqueID projectUID)
{
	HPMSdkSession *session = SessionManager::getInstance().Session();
	//Create a sprint to commit items to
	HPMTaskCreateUnified NewTestCycle;
	NewTestCycle.m_Tasks.resize(1);
	NewTestCycle.m_Tasks[0].m_bIsProxy = false;
	NewTestCycle.m_Tasks[0].m_LocalID = -1;
	NewTestCycle.m_Tasks[0].m_TaskLockedType = EHPMTaskLockedType_SprintItem;

	//The new test cycle will end up at the top of the schedule.
	HPMTaskCreateUnifiedReference PrevRefID;
	PrevRefID.m_bLocalID = false;
	PrevRefID.m_RefID = -1;
	NewTestCycle.m_Tasks[0].m_PreviousRefID = PrevRefID;

	HPMTaskCreateUnifiedReference PrevWorkPrioRefID;
	PrevWorkPrioRefID.m_bLocalID = false;
	PrevWorkPrioRefID.m_RefID = -2;
	NewTestCycle.m_Tasks[0].m_PreviousWorkPrioRefID = PrevWorkPrioRefID;

	HPMChangeCallbackData_TaskCreateUnified TaskCreateReturn = session->TaskCreateUnifiedBlock(projectUID, NewTestCycle);

	// We know that we are only creating one item, so we'll get the identifier for that one.
	HPMUniqueID sprintRefID = TaskCreateReturn.m_Tasks[0].m_TaskRefID;
	HPMUniqueID sprintTaskID = session->TaskRefGetTask(sprintRefID);

	session->TaskSetFullyCreated(sprintTaskID);
	session->TaskSetDescription(sprintTaskID, name);
	session->TaskSetDuration(sprintTaskID, duration);
	return sprintRefID;
}
/*********************************************
* Creates a new bug.
* Params:
*	name - the name of the new bug
*	projectUID - project to create the bug in
* Returns:
*   the ref id of the new bug
*********************************************/
HPMUniqueID HansoftUtils::createBug(HPMString name, HPMUniqueID projectUID)
{
	HPMSdkSession *session = SessionManager::getInstance().Session();
	HPMUniqueID projectQAUID = session->ProjectUtilGetQA(projectUID);
	// Create a new one
	HPMTaskCreateUnified createData;
	createData.m_Tasks.resize(1);

	// Set previous to -1 to make it the top task.
	HPMTaskCreateUnifiedReference prevRefID;
	prevRefID.m_RefID = -1;
	HPMTaskCreateUnifiedReference prevWorkPrioRefID;
	prevWorkPrioRefID.m_RefID = -2;

	createData.m_Tasks[0].m_LocalID = 1;
	createData.m_Tasks[0].m_PreviousRefID = prevRefID;
	createData.m_Tasks[0].m_PreviousWorkPrioRefID = prevWorkPrioRefID;

	HPMChangeCallbackData_TaskCreateUnified TaskCreateReturn = session->TaskCreateUnifiedBlock(projectQAUID, createData);
	if (TaskCreateReturn.m_Tasks.size() == 1)
	{
		// The returned is a bug ref in the project container. We need the task id not the reference id.
		HPMUniqueID bugRefID = TaskCreateReturn.m_Tasks[0].m_TaskRefID;
		HPMUniqueID bugUID = session->TaskRefGetTask(bugRefID);
		session->TaskSetDescription(bugUID, name);
		// When we set fully created the task becomes visible to users.
		session->TaskSetFullyCreated(bugUID);
		return bugRefID;
	}
	return -1;
}
/*********************************************
* Commits the list of backlog items to the sprint. Will handle if both parent and children exists in the list
* by committing the parent with all its children.
* Params:
*	sprintRefID - the sprint to commit the tasks to
*	projectUID - the project the sprint exists in
*   backlogItems - the list of backlog item ID's to commit
*********************************************/
void HansoftUtils::commitBacklogItems(HPMUniqueID sprintRefID, HPMUniqueID projectUID, vector<HPMUniqueID> backlogItems)
{
	HPMSdkSession *session = SessionManager::getInstance().Session();
	HPMTaskCreateUnified committedBacklogItems;
	HPMTaskCreateUnifiedReference sprintRefObj;
	sprintRefObj.m_bLocalID = false;
	sprintRefObj.m_RefID = sprintRefID;


	// Loop over all the created tasks and add them to the newly created test cycle
	HPMTaskCreateUnifiedReference prevRef = sprintRefObj;
	unsigned index = 0;
	for (unsigned int i = 0; i < backlogItems.size(); ++i)
	{
		if (!HansoftUtils::isParentIsList(backlogItems[i], backlogItems))
		{
			std::vector<HPMTaskCreateUnifiedEntry> testCaseEntries = createCommitEntryList(backlogItems[i], index, prevRef, sprintRefObj);
			committedBacklogItems.m_Tasks.insert(committedBacklogItems.m_Tasks.end(), testCaseEntries.begin(), testCaseEntries.end());

			// Set the id to the current task so that the next created task will end up after this one. 
			prevRef.m_bLocalID = true;
			prevRef.m_RefID = index;
		}
	}
	session->TaskCreateUnifiedBlock(projectUID, committedBacklogItems);
}