#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned long	U32;
typedef 		 char	C08;

#define NUM_STR_MAX	  11					// Contain '\0'
#define OPE_STR_MAX	  (NUM_STR_MAX + 7)
#define OPE_COUNT_MAX 2000000
#define INPUT_NUM_MIN 0
#define INPUT_NUM_MAX 2000000000
#define QUEUE_TOP_IDX 0

static void Insert_Num_Void(U32 *U32_Queue_p, U32 *U32_MaxNumIdx, U32 *U32_QueueEndIdx, U32 U32_InputNum);		// Function of insert the num to queue
static void Extract_Num_Void(U32 *U32_Queue_p, U32 *U32_MaxNumIdx, U32 *U32_QueueEndIdx);	// Function of extract the maximum num of queue


/***********************************************************************************
 ++module <main>
 ++outline
	main function
 ++arguments
	<>			<>					[]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
int main(void)
{
	// Valiable declaration
	C08 C08_OpeStr[OPE_STR_MAX]   = {'\0'};	// Operation string ("insert XX", "extract", "end")
	C08 C08_InputNum[NUM_STR_MAX] = {'\0'}; // Input num(C08)
	U32 U32_InputNum    = 0;				// Input num(U32)
	U32 *U32_Queue_p;						// Queue
	U32 U32_MaxNumIdx   = QUEUE_TOP_IDX;	// Max num index of queue
	U32 U32_QueueEndIdx = QUEUE_TOP_IDX;	// Index of queue end
	C08 *C08_IsOpeStrMatch_p;				// Check the Operation
	U32 U32_i = 0;							// Loop valiable
	
	// Get malloc
	U32_Queue_p = (U32 *)malloc(sizeof(U32) * OPE_COUNT_MAX);
	if(NULL == U32_Queue_p)
	{
		return 1;
	}
	
	printf("Size = %ld\n", sizeof(U32_Queue_p));
	printf("Size = %d\n", OPE_COUNT_MAX);
	printf("Size = %ld\n", sizeof(U32));
	
	// Initialize the queue
	for(U32_i = 0; U32_i < OPE_COUNT_MAX; U32_i++)
	{
		U32_Queue_p[U32_i] = 0;
	}
	// memset(&U32_Queue_p, OPE_COUNT_MAX, 0);
	U32_i = 0;
	
	// Input the operation
	while(U32_i < OPE_COUNT_MAX)
	{
		fgets(C08_OpeStr, OPE_STR_MAX, stdin);
		
		if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "insert") ) )			// Insert the num
		{
			printf("insert\n");
			// Get the number from "C08_OpeStr"
			strncpy(C08_InputNum, C08_OpeStr + (OPE_STR_MAX - NUM_STR_MAX), NUM_STR_MAX);
			U32_InputNum = atoi(C08_InputNum);
			
			// If the input num is out of the range, do nothing
			if(INPUT_NUM_MAX < U32_InputNum)
			{
				
			}
			else
			{
				// Insert the num
				Insert_Num_Void(&U32_Queue_p[QUEUE_TOP_IDX], &U32_MaxNumIdx, &U32_QueueEndIdx, U32_InputNum);
			}
		}
		else if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "extract") ) )		// Extract the num
		{
			printf("extract\n");
			// If the queue is empty, do nothing
			if(QUEUE_TOP_IDX == U32_QueueEndIdx)
			{
				
			}
			else
			{
				// Extract the num
				Extract_Num_Void(&U32_Queue_p[QUEUE_TOP_IDX], &U32_MaxNumIdx, &U32_QueueEndIdx);
			}
		}
		else if( NULL != ( C08_IsOpeStrMatch_p = strstr(C08_OpeStr, "end") ) )			// End
		{
			printf("end\n");
			break;
		}
		else
		{
			printf("else\n");
			// Do nothing
		}
		
		// Reset the operation string
		memset(&C08_OpeStr[0], '\0', sizeof(C08_OpeStr));
		U32_i++;
	}
	
	// Release the queue
	free(U32_Queue_p);
	
	return 0;
}

/***********************************************************************************
 ++module <Insert_Num_Void>
 ++outline
	Insert the num to queue
 ++arguments
	<U32>	<U32_Queue_p>		[Queue]
	<U32>	<U32_MaxNumIdx>		[Index of maximim num]
	<U32>	<U32_QueueEndIdx>	[Index of queue end]
	<U32>	<U32_InputNum>		[Input num]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
static void Insert_Num_Void(U32 *U32_Queue_p, U32 *U32_MaxNumIdx, U32 *U32_QueueEndIdx, U32 U32_InputNum)
{
	U32_Queue_p[*U32_QueueEndIdx] = U32_InputNum;			// Insert the num
	printf("Queue[%ld] = %ld\n", *U32_QueueEndIdx, U32_Queue_p[*U32_QueueEndIdx]);
	
	// Update the max num
	if(U32_InputNum > U32_Queue_p[*U32_MaxNumIdx])
	{
		*U32_MaxNumIdx = *U32_QueueEndIdx;
	}
	
	// Update the end index
//	(*U32_QueueEndIdx)++;
	
	return;
}


/***********************************************************************************
 ++module <Extract_Num_Void>
 ++outline
	Extract the maximum num of queue
 ++arguments
	<U32>	<U32_Queue_p>		[Queue pointer]
	<U32>	<U32_MaxNumIdx>		[Index of maximim num]
	<U32>	<U32_QueueEndIdx>	[Index of queue end]
 ++supp
 	<return>
 	  nothing
 ++end_module
************************************************************************************/
static void Extract_Num_Void(U32 *U32_Queue_p, U32 *U32_MaxNumIdx, U32 *U32_QueueEndIdx)
{
	U32 U32_i;
	
	printf("%ld\n", U32_Queue_p[*U32_MaxNumIdx]);				// Disp the max num
	
	// Update the queue
	U32_i = (*U32_MaxNumIdx) + 1;
	while(1)
	{
		U32_Queue_p[U32_i - 1] = U32_Queue_p[U32_i];
		
		if(U32_i == *U32_QueueEndIdx)
		{
			// Update queue end
			U32_Queue_p[U32_i] = 0;
			(*U32_QueueEndIdx)--;
			break;
		}
		U32_i++;
	}
	
	// Update the maximim num
	*U32_MaxNumIdx = QUEUE_TOP_IDX;
	U32_i          = (*U32_MaxNumIdx) + 1;
	
	while(1)
	{
		if(U32_Queue_p[U32_i] > U32_Queue_p[*U32_MaxNumIdx])
		{
			*U32_MaxNumIdx = U32_i;
		}
		
		// If "U32_i" is "U32_QueueEndIdx", break
		// If "U32_i" is not "U32_QueueEndIdx", update "U32_i"
		if(U32_i == *U32_QueueEndIdx)
		{
			break;
		}
		else
		{
			U32_i++;
		}
	}
	
	return;
}


/*
insert 8
insert 2
extract
insert 10
extract
insert 11
extract
extract
end
*/
