/******************************************************************************
 ** al_prog_reminder.c: Program Reminder component. It holds  and manage list of the program
 **					reminders for the service and event component.
 **
 ** Copyright(c) 2008 Wipro Technologies - All Rights Reserved
 ** Author : Soumya Pandiyattu
 **
 ** $Id: ACPR_Component.c,v 1.5 2009/07/07 06:19:56 qinhe Exp $
 ******************************************************************************/
#include "al_prog_reminder.h"
#include "al_basictypes.h"
#include "ai_debug_config.h"
#include "al_scheduler.h"
#include "al_time.h"
#include "al_fw.h"
#include "ai_time.h"
#include "gl_mutex.h"

/* debug and error print */
#if AL_PR_DEBUG_CHK
	#define PR_DEBUG(fmt, arg...) \
	do { \
		UMFDBG(0,"[Debug]%s: %d Line \n", __FUNCTION__, __LINE__); \
		UMFDBG(0,fmt, ##arg); \
	} while(0)
#else
	#define PR_DEBUG(fmt, arg...);
#endif

#if AL_PR_ERROR_CHK
	#define PR_ERROR(fmt, arg...) \
	do { \
		UMFDBG(0,"[Error]%s: %d Line \n", __FUNCTION__, __LINE__); \
		UMFDBG(0,fmt, ##arg); \
	} while(0)
#else
	#define PR_ERROR(fmt, arg...);
#endif

#define PR_MUTEX_LOCK(sem_id) \
	if(GL_SUCCESS != GL_MutexLock(sem_id)){\
		PR_ERROR("Mutex Lock FAILED\n");}\
	else {PR_DEBUG("Mutex Lock SUCCESS\n");}

#define PR_MUTEX_UNLOCK(sem_id) \
	if(GL_SUCCESS != GL_MutexUnlock(sem_id)){\
		PR_ERROR("Mutex UnLock FAILED\n");}\
	else {PR_DEBUG("Mutex Unlock SUCCESS\n");}


static al_uint8 g_head_node;
static GL_Mutex_t g_pr_mutex_id;

/* Static Variables */
static PR_details_t  *g_event_details = NULL;
static  AL_SCH_time_t app_schd_time[AL_SCH_MAX_NO_OF_CALLBACK];
static AL_PR_Init_Param_t g_Init_Param; /*we can set it in application layer*/
static	al_int Prog_remind_id = AL_SCH_INVALID_ID; // The earliest id of schdule module.
static Boolean g_initSuccess = FALSE;
static al_bool _AI_PR_CheckReminderOverlapForSerEx(al_uint32 start_sec,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum);
static al_bool _AI_PR_CheckReminderOverlapForSer(al_uint32 start_sec);
static  AL_Return_t _AI_PR_SetDefaultValue ( void );
static AL_Return_t _AI_PR_Schedule ( al_uint8 offset );
static AL_Return_t _AI_PR_Reschedule ( al_uint8 offset );
static al_uint8 _AI_PR_GetFreeNode ( void );
static void _AI_PR_InsertNode (al_uint8 count );
static al_bool _AI_PR_CheckReminderAtTimeEx(al_uint32 sec, AL_SCH_sched_id_t *id, AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum);
static al_bool _AI_PR_CheckReminderOverlapEx(al_uint32 start_sec, al_uint32 end_sec,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum);
static al_bool _AI_PR_CheckReminderAtTime(al_uint32 sec, AL_SCH_sched_id_t *id);
static al_bool _AI_PR_CheckReminderOverlap(al_uint32 start_sec, al_uint32 end_sec);
static AL_Return_t _AI_PR_FillDetails( AL_PR_details_t *details);
static AL_Return_t _AI_PR_RetrieveRemDetails(void);
static AL_Return_t _AI_PR_CheckSRVInvalid(AL_RecHandle_t handle);

/*	function */
static Boolean _AI_PR_IsInit (void)
{
	return g_initSuccess;
}
static AL_Return_t _AI_PR_CheckSRVInvalid(AL_RecHandle_t handle)
{
	AL_DB_EDBType_t DBType = AL_DBTYPE_MAX;
	AL_DB_ERecordType_t RecordType;
	AL_Return_t ret_val = AL_SUCCESS;
	AL_ServiceDetail_t pDetailData;
	AL_NetworkDetail_t NetworkData;
	AL_MultiplexDetail_t MultiplexData;

	ret_val = AL_DB_GetRecordType(handle, &DBType, &RecordType);

	switch (DBType)
	{
		case AL_DBTYPE_DVB_ATV:
			 if (RecordType == AL_RECTYPE_ATVSERVICE)
			 {
				ret_val = AL_DB_QueryDetail(handle, (void *)&pDetailData);
			 }
			break;

		case AL_DBTYPE_DVB_T:
			if (RecordType == AL_RECTYPE_DVBNETWORK)
			{
				ret_val = AL_DB_QueryDetail(handle, (void*)&NetworkData);
			}
			else if (RecordType == AL_RECTYPE_DVBMULTIPLEX)
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&MultiplexData);
			}
			else
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&pDetailData);
			}
			break;

		case AL_DBTYPE_DVB_C:
			 if (RecordType == AL_RECTYPE_DVBMULTIPLEX)
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&MultiplexData);
			}
			else
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&pDetailData);
			}
			break;

		case AL_DBTYPE_DVB_S:

			break;

		#ifdef CONFIG_ISDB_SYSTEM
		case AL_DBTYPE_DVB_SBTVD:
			if (RecordType == AL_RECTYPE_DVBNETWORK)
			{
				ret_val = AL_DB_QueryDetail(handle, (void*)&NetworkData);
			}
			else if (RecordType == AL_RECTYPE_DVBMULTIPLEX)
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&MultiplexData);
			}
			else
			{
				ret_val = AL_DB_QueryDetail(handle, (void *)&pDetailData);
			}
			break;

		#endif
		default:
			break;

	}
	if(ret_val != AL_SUCCESS)
	{
		PR_ERROR("NO SUCH SRV ID\n");
		ret_val = AL_REMINDER_SRV_NOT_PRESENT;
	}

	return ret_val;
}

/************************************************************************
 ** name			:_AI_PR_SetDefaultValue()
 **
 ** description		: This API initialise this component with default value
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
static AL_Return_t _AI_PR_SetDefaultValue ( void )
{
	al_uint8 count;
	AL_Return_t ret = AL_SUCCESS;

	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}
	
	g_head_node = g_Init_Param.MaxNumOfReminders;

	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	if (pf_PR_GetContext != NULL)
	{
		for( count = 0; count < g_Init_Param.MaxNumOfReminders; count++)
		{
			g_event_details[count].details.occupied= al_false;
			g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders ;
			ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
						&g_event_details[count], count);
			if (ret != AL_SUCCESS)
			{
				return ret;
			}
		}
	}
	return AL_SUCCESS;
}

/************************************************************************
 ** name				:	_AI_PR_Schedule
 **
 ** description		: 	API schedule reminder if enabled.
 **
 ** input parameters	: 	none
 **
 ** output parameters	: 	none
 **
 ** return type		: 	AL_Return_t
 ************************************************************************/
 static AL_Return_t _AI_PR_Schedule ( al_uint8 offset )
{
	AL_Return_t ret_val = AL_FAILURE;
	AL_SCH_details_t sch_details;

	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	if ( g_event_details[offset].details.enable == al_false )
	{
		return AL_FAILURE;
	}

	if ( g_event_details[offset].details.snooze_time_secs == 0 )
	{
		sch_details.sch_event = AL_SCH_TYPE_SINGLE;
	}
	else
	{
		sch_details.sch_event = AL_SCH_TYPE_REPEAT;
	}

	if ( g_event_details[offset].details.rem_type == AL_PR_EVT_REM )
	{
		sch_details.sch_event |= AL_SCH_TYPE_PRG_SCH | AL_SCH_TYPE_MULTI_EVENT;
	}
	else
	{
		sch_details.sch_event |= AL_SCH_TYPE_SRV_SCH| AL_SCH_TYPE_MULTI_EVENT;
	}

	sch_details.sch_snooze = g_event_details[offset].details.snooze_time_secs ;
	sch_details.sch_time = g_event_details[offset].details.start_local_time_secs ;
	sch_details.sch_user_para = offset;
	memcpy(sch_details.app_schd_time, app_schd_time, sizeof(sch_details.app_schd_time));

	/* schedule the events */
	ret_val = AL_SCH_ScheduleEvent(&sch_details , &(g_event_details[offset].sch_id), NULL);
	if ( AL_SUCCESS != ret_val )
	{
		PR_ERROR(" Error in Scheduling the event");
		g_event_details[offset].details.enable = al_false;
	}
	return ret_val;
}

/************************************************************************
 ** name				:	_AI_PR_GetFreeNode
 **
 ** description		: 	This API get free reminder node
 **
 ** input parameters	: 	none
 **
 ** output parameters	: 	none
 **
 ** return type		: 	AL_Return_t
 ************************************************************************/
 static al_uint8 _AI_PR_GetFreeNode ( void )
{
	al_uint8 count;
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return 0;
	}

	for( count = 0; count < g_Init_Param.MaxNumOfReminders; count++)
	{
		if( g_event_details[count].details.occupied == al_false)
		{
			break;
		}
	}
	return count;
}

/************************************************************************
 ** name				:	_AI_PR_FillDetails
 **
 ** description		: 	This API Fills the details strucutre of component
 **
 ** input parameters	:details: Details provided by application.
 ** output parameters	: 	none
 **
 ** return type		: 	AL_Return_t
 ************************************************************************/
static AL_Return_t _AI_PR_FillDetails ( AL_PR_details_t* details)
{
	if(details->rem_type == AL_PR_EVT_REM ||details->rem_type == AL_PR_SRV_REM )
	{
		if(AL_SUCCESS != _AI_PR_CheckSRVInvalid(details->rem_details.handle))
		{
			PR_ERROR("NO SUCH SRV ID\n");
			return AL_REMINDER_SRV_NOT_PRESENT;
		}

		/* Here we should check the validation of the event id */
		//ret_val = AIEC_get_eventid_of_num(&handle,
		//							g_event_details[count].details.rem_details.event_sch_details.event_no,
		//							&event_id);
		return AL_SUCCESS;
	}

	return AL_SUCCESS;

}

/************************************************************************
 ** name				:	_AI_PR_InsertNode
 **
 ** description		: 	This API insert node at the head of the reminder list.
 **
 ** input parameters	: 	none
 **
 ** output parameters	: 	none
 **
 ** return type		: 	AL_Return_t
 ************************************************************************/
static void _AI_PR_InsertNode ( al_uint8 count )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return;
	}

	al_uint8 index , prev_index = g_Init_Param.MaxNumOfReminders;

	/* Insert at the head of the link list */
	for(index = g_head_node; index < g_Init_Param.MaxNumOfReminders; index = g_event_details[index].next_index)
	{
		if((g_event_details[index].details.occupied == al_true)
			&& (g_event_details[index].details.start_local_time_secs > g_event_details[count].details.start_local_time_secs))
		{
				break;
		}
		prev_index = index;
	}

	if ( prev_index >= g_Init_Param.MaxNumOfReminders )
	{
		/* First node is getting  replaced */
		g_event_details[count].next_index = index;
		g_head_node = count;
	}
	else
	{
		g_event_details[count].next_index = g_event_details[prev_index].next_index;
		g_event_details[prev_index].next_index = count;
	}
	g_event_details[count].details.occupied = al_true;
	return;
}

/************************************************************************
 ** name				:	_AI_PR_Compare_EVTTime
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one
 **
 ** input parameters	:	al_uint32 In_StartTime  --Setting event start time
 **                         al_uint32 In_EndTime    --Setting event start time
 **                         al_uint32 Cmp_StartTime --exist event start time
 **                         al_uint32 Cmp_EndTime   --exist event end time
 ** output parameters	:   none
 **
 ** return type			:	if timer conflict then return al_true
 ************************************************************************/
static al_bool _AI_PR_Compare_EVTTime(al_uint32 In_StartTime, al_uint32 In_EndTime,
                    al_uint32 Cmp_StartTime, al_uint32 Cmp_EndTime)
{

    if ((In_StartTime >= Cmp_StartTime)
        && (In_StartTime < Cmp_EndTime))
    {
        return al_true;
    }

    if ((In_EndTime > Cmp_StartTime)
        && (In_EndTime <= Cmp_EndTime))
    {
        return al_true;
    }

    if ((In_StartTime < Cmp_StartTime)
        && (In_EndTime >= Cmp_EndTime))
    {
        return al_true;
    }

	return al_false;
}

/************************************************************************
 ** name				:	_AI_PR_CheckReminderAtTime
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderAtTime(al_uint32 sec, AL_SCH_sched_id_t *id)
{
	al_uint8 count;

	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		if( (g_event_details[count].details.start_local_time_secs/60 == sec/60) &&
			( g_event_details[count].details.occupied == al_true ) &&
			(g_event_details[count].details.enable == al_true))
		{
			*id = g_event_details[count].sch_id;
			return al_true;
		}
	}
	return al_false;
}

/************************************************************************
 ** name				:	_AI_PR_CheckReminderAtTimeEx
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderAtTimeEx(al_uint32 sec, AL_SCH_sched_id_t *id, AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	al_uint8 count;
	al_bool ret = al_false;
	al_uint8 ConflictNumcount = 0;

	if((ConflictTimerID == NULL)
		||(ConflictTimerNum == NULL))
	{
		return ret;
	}
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		if( (g_event_details[count].details.start_local_time_secs/60 == sec/60) &&
			( g_event_details[count].details.occupied == al_true ) &&
			(g_event_details[count].details.enable == al_true))
		{
			*id = g_event_details[count].sch_id;
			ConflictTimerID[ConflictNumcount++] = g_event_details[count].sch_id;
			ret = al_true;
		}
	}
	*ConflictTimerNum = ConflictNumcount;
	return ret;
}
/************************************************************************
 ** name				:	_AI_PR_CheckReminderOverlap
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one especially for recording event
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderOverlap(al_uint32 start_sec, al_uint32 end_sec)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	al_uint8 count;

	for ( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		PR_DEBUG("++++++++++++++++++++++++++++++\n");
		PR_DEBUG("start time in link [%d]===================== %d\n",count,g_event_details[count].details.start_local_time_secs);
		PR_DEBUG("end  time in link  [%d]=====================  %d\n",count,g_event_details[count].details.rem_details.event_end_time_insec);
		PR_DEBUG("++++++++++++++++++++++++++++++\n");

		if (g_event_details[count].details.rem_type == AL_PR_EVT_REM
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true))
		{
		    if (_AI_PR_Compare_EVTTime(start_sec, end_sec, g_event_details[count].details.start_local_time_secs,
                    g_event_details[count].details.rem_details.event_end_time_insec))
            {
    			return al_true;
            }
		}

		if (g_event_details[count].details.rem_type == AL_PR_SRV_REM
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true)
			&&((start_sec< g_event_details[count].details.start_local_time_secs)
			    &&(end_sec > g_event_details[count].details.start_local_time_secs)))
		{
			return al_true;
		}
	}
	return al_false;
}

/************************************************************************
 ** name				:	_AI_PR_CheckReminderOverlapEx
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one especially for recording event
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderOverlapEx(al_uint32 start_sec, al_uint32 end_sec,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	al_uint8 count;
	al_bool ret = al_false;
	al_uint8 ConflictNumcount = 0;
	if((ConflictTimerID == NULL)
		||(ConflictTimerNum == NULL))
	{
		return ret;
	}
	for ( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		PR_DEBUG("++++++++++++++++++++++++++++++\n");
		PR_DEBUG("start time in link [%d]===================== %d\n",count,g_event_details[count].details.start_local_time_secs);
		PR_DEBUG("end  time in link  [%d]=====================  %d\n",count,g_event_details[count].details.rem_details.event_end_time_insec);
		PR_DEBUG("++++++++++++++++++++++++++++++\n");

		if (g_event_details[count].details.rem_type == AL_PR_EVT_REM
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true))
		{
		    if (_AI_PR_Compare_EVTTime(start_sec, end_sec, g_event_details[count].details.start_local_time_secs,
                    g_event_details[count].details.rem_details.event_end_time_insec))
            {
    			ConflictTimerID[ConflictNumcount++] = g_event_details[count].sch_id;
    			ret = al_true;
            }
		}

		if (g_event_details[count].details.rem_type == AL_PR_SRV_REM
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true)
			&&((start_sec< g_event_details[count].details.start_local_time_secs)
			&&(end_sec > g_event_details[count].details.start_local_time_secs)))
		{
			ConflictTimerID[ConflictNumcount++] = g_event_details[count].sch_id;
			ret = al_true;
		}
	}
	*ConflictTimerNum = ConflictNumcount;
	return ret;
}
/************************************************************************
 ** name				:	_AI_PR_CheckReminderOverlapForSer
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one especially for recording event
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderOverlapForSer(al_uint32 start_sec)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	al_uint8 count;
	for ( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		if ((g_event_details[count].details.rem_type == AL_PR_EVT_REM)
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true)
			&&( (start_sec >= g_event_details[count].details.start_local_time_secs)
			&& (start_sec < g_event_details[count].details.rem_details.event_end_time_insec)))
		{
			return al_true;
		}
	}
	return al_false;
}

/************************************************************************
 ** name				:	_AI_PR_CheckReminderOverlapForSerEx
 **
 ** description			:	checks if the time of scheduled event collides with
 **								previous one especially for recording event
 **
 ** input parameters	:	none
 **
 ** output parameters	:   none
 **
 ** return type			:	AL_Return_t
 ************************************************************************/
static al_bool _AI_PR_CheckReminderOverlapForSerEx(al_uint32 start_sec,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return al_false;
	}

	al_uint8 count;
	al_bool ret = al_false;
	al_uint8 ConflictNumcount = 0;
	if((ConflictTimerID == NULL)
		||(ConflictTimerNum == NULL))
	{
		return ret;
	}
	for ( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		if ((g_event_details[count].details.rem_type == AL_PR_EVT_REM)
			&& (g_event_details[count].details.occupied == al_true )
			&& (g_event_details[count].details.enable == al_true)
			&&( (start_sec >= g_event_details[count].details.start_local_time_secs)
			&& (start_sec < g_event_details[count].details.rem_details.event_end_time_insec)))
		{
			ConflictTimerID[ConflictNumcount++] = g_event_details[count].sch_id;
			ret = al_true;
		}
	}
	*ConflictTimerNum = ConflictNumcount;
	return ret;
}

/************************************************************************
 ** name				:	_AI_PR_Reschedule
 **
 ** description		: 	API schedule reminder if enabled.
 **
 ** input parameters	: 	none
 **
 ** output parameters	: 	none
 **
 ** return type		: 	AL_Return_t
 ************************************************************************/
 static AL_Return_t _AI_PR_Reschedule ( al_uint8 offset )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_Return_t ret_val = AL_FAILURE;
	AL_SCH_details_t sch_details;

	if ( g_event_details[offset].details.enable == al_false )
	{
		return AL_SUCCESS;
	}

	if ( g_event_details[offset].details.snooze_time_secs == 0 )
	{
		sch_details.sch_event = AL_SCH_TYPE_SINGLE;
	}
	else
	{
		sch_details.sch_event = AL_SCH_TYPE_REPEAT;
	}

	if ( g_event_details[offset].details.rem_type == AL_PR_EVT_REM )
	{
		sch_details.sch_event |= AL_SCH_TYPE_PRG_SCH | AL_SCH_TYPE_MULTI_EVENT;
	}
	else
	{
		sch_details.sch_event |= AL_SCH_TYPE_SRV_SCH | AL_SCH_TYPE_MULTI_EVENT;
	}

	sch_details.sch_snooze = g_event_details[offset].details.snooze_time_secs ;
	sch_details.sch_time = g_event_details[offset].details.start_local_time_secs ;
	sch_details.sch_user_para = offset;

	memcpy(sch_details.app_schd_time, app_schd_time, sizeof(sch_details.app_schd_time));
	ret_val = AL_SCH_ReScheduleEvent(&g_event_details[offset].sch_id, &sch_details);
	if( AL_INVALID_SCH_ID == ret_val )
	{
		ret_val = _AI_PR_Schedule (offset);
	}

	if ( AL_SUCCESS != ret_val )
	{
		PR_ERROR(" Error in reScheduling the event");
		g_event_details[offset].details.enable = al_false;
	}

	return ret_val;
}

 /************************************************************************
  ** name				 :	 _AI_PR_ModyfiSnoozeEvent
  **
  ** description	 :	 If the current event is repeate event, but the current scheduling time has expired, so need to update the schedule time
  **                               The action in the pr module initialization or passive update the system time for the first time be triggered.
  ** input parameters	 :	 nil
  **
  ** output parameters	 :	 nil
  ** return type	 :	 void
  ************************************************************************/
 static AL_Return_t _AI_PR_ModyfiSnoozeEvent(al_uint8 count)
{
	al_uint32	CurTimeInSec = 0;
	al_uint32  RepeatTimes = 0;
	al_uint32  i = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = al_null;
	AL_Return_t ret_val = AL_SUCCESS;

	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	if (count > AL_PR_GetMaxNoOfReminders())
	{
		return AL_FAILURE;
	}

	if (g_event_details[count].details.snooze_time_secs == 0)
	{
		return AL_FAILURE;
	}

	AL_FW_GetContextCb(&pf_PR_GetContext);

	AL_Time_GetCurTimeInSecs(&CurTimeInSec);
	CurTimeInSec += app_schd_time[0];
	if (CurTimeInSec > g_event_details[count].details.start_local_time_secs)
	{
		RepeatTimes = (CurTimeInSec - g_event_details[count].details.start_local_time_secs)/g_event_details[count].details.snooze_time_secs;
		i = (CurTimeInSec - g_event_details[count].details.start_local_time_secs)%g_event_details[count].details.snooze_time_secs;
		PR_DEBUG("RepeatTimes is %d, i is %d\n\n",RepeatTimes,i);
		g_event_details[count].details.start_local_time_secs += (g_event_details[count].details.snooze_time_secs*RepeatTimes);
		g_event_details[count].details.rem_details.event_end_time_insec += (g_event_details[count].details.snooze_time_secs*RepeatTimes);
		if (i != 0 || RepeatTimes == 0)
		{
			g_event_details[count].details.start_local_time_secs += (g_event_details[count].details.snooze_time_secs);
			g_event_details[count].details.rem_details.event_end_time_insec += (g_event_details[count].details.snooze_time_secs);
		}
		
		if (pf_PR_GetContext != NULL)
		{
			ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
				&g_event_details[count], count);
			if (ret_val != AL_SUCCESS)
			{
				return ret_val;
			}
		}
	}
	return AL_SUCCESS;
}


/************************************************************************
 ** name				:	_AI_PR_RetrieveRemDetails
 **
 ** description		:	Retrives the stored details and genrate the PR
 **						global database.
 **
 ** input parameters	:	nil
 **
 ** output parameters	:  	nil
 ** return type		:	void
 ************************************************************************/
static AL_Return_t _AI_PR_RetrieveRemDetails(void)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_Return_t ret_val = AL_SUCCESS;
	al_uint8 count;
	al_uint8 prev_index;

	/* Load data from persistence memory */
	frmwrk_pfOpConext_t pf_PR_GetContext = al_null;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	if (pf_PR_GetContext != al_null)
	{
		memset(g_event_details, 0, sizeof(PR_details_t) * g_Init_Param.MaxNumOfReminders);
		ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_READ,
						(al_void *)g_event_details, 0);
		if (ret_val != AL_SUCCESS)
		{
			return ret_val;
		}

	}

	/* For the link list*/
	for(count = 0 , g_head_node = g_Init_Param.MaxNumOfReminders; count < g_Init_Param.MaxNumOfReminders ; count ++)
	{

		if(g_event_details[count].details.occupied == al_true)
		{
			_AI_PR_ModyfiSnoozeEvent(count);
			_AI_PR_InsertNode(count);
		}
	}

	/*For Scheduler and delete the invalid reminders*/
	for( count = g_head_node, prev_index = g_Init_Param.MaxNumOfReminders;
		count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		if (g_event_details[count].details.occupied == al_true)
		{
			if(AL_SUCCESS != (ret_val = _AI_PR_Schedule(count)))
			{
				/*** DELETE THE NODE ***/
				if ( prev_index >= g_Init_Param.MaxNumOfReminders )
				{
					g_head_node = g_event_details[count].next_index;
				}
				else
				{
					g_event_details[prev_index].next_index = g_event_details[count].next_index ;
				}
				g_event_details[count].details.occupied = al_false;

				if (pf_PR_GetContext != NULL)
				{
					ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
						&g_event_details[count], count);
					if (ret_val != AL_SUCCESS)
					{
						return ret_val;
					}
				}
			}
			else
			{
				prev_index = count;
			}
		}
	}

	return AL_SUCCESS;
}
/*****************************************************************************
** FUNCTION : AL_PR_SetInitParam
**
** DESCRIPTION :
**				Set init Param for Prog Reminder.
**
** PARAMETERS :
**				AL_PR_Init_Param_t
**
** RETURN VALUES:
**				void
*****************************************************************************/

al_void AL_PR_SetInitParam(AL_PR_Init_Param_t  *Init_param)
{

	/*the time of show popmessage befor event coming.*/
	g_Init_Param.app_schd_time[0] = Init_param->app_schd_time[0];
	PR_DEBUG("notify time in sec = %d\n", g_Init_Param.app_schd_time[0]);
	/*reserves*/
	g_Init_Param.app_schd_time[1] = Init_param->app_schd_time[1];
	g_Init_Param.app_schd_time[2] = Init_param->app_schd_time[2];

	/*the max number of  event.*/
	g_Init_Param.MaxNumOfReminders = Init_param->MaxNumOfReminders;
	PR_DEBUG("the max number of event = %d\n", g_Init_Param.MaxNumOfReminders);

	if ((g_Init_Param.app_schd_time[0] <= 0)||(g_Init_Param.MaxNumOfReminders <=0))
	{
		PR_ERROR("Invalided  param\n\n");
	}
}
/*****************************************************************************
** FUNCTION : AI_PR_Init
**
** DESCRIPTION :
**				This function is used to initialise program reminder module.
**
** PARAMETERS :
**				None
**
** RETURN VALUES:
**				AL_SUCCESS
*****************************************************************************/
 AL_Return_t AL_PR_Init ( void )
{
	AL_Return_t ret_val;

	if (_AI_PR_IsInit() == TRUE)
	{
		PR_ERROR(" init already\n");
		return AL_INITIALIZE_ALREADY;
	}

	if ( g_pr_mutex_id != 0 )
	{
		/* Already intialised */
		return AL_FAILURE;
	}

	g_event_details = (PR_details_t *)GL_MemAlloc(sizeof(PR_details_t)*g_Init_Param.MaxNumOfReminders);
	if (g_event_details == NULL)
	{
		PR_ERROR("FAILED TO malloc memory for g_event_details\n\n");
		return  AL_FAILURE;
	}

	/* Create Semaphore for the Global value */
	if(GL_SUCCESS != GL_MutexCreate(PR_MUXTEX_NAME, &g_pr_mutex_id))
	{
		PR_ERROR("FAILED TO CREATE SEMAPHORE\n\n");
		GL_MemFree(g_event_details);
        g_event_details = NULL;
		return AL_FAILURE;
	}
	
	/* time of show popmessage befor event coming*/
	app_schd_time[0] = g_Init_Param.app_schd_time[0];
	/*reserves*/
	app_schd_time[1] = g_Init_Param.app_schd_time[1];
	app_schd_time[2] = g_Init_Param.app_schd_time[2];

	g_head_node = g_Init_Param.MaxNumOfReminders;

	/* malloc , mutex is ok*/
	g_initSuccess = TRUE;

	ret_val = _AI_PR_RetrieveRemDetails();

	if ( ret_val == AL_CORRUPTED_MEMORY )
	{
		/* Load the default value */
		ret_val = _AI_PR_SetDefaultValue ();
	}

	AL_PR_Update(0, 0);

	return ret_val;
}
/************************************************************************
 ** name				:AI_PR_term()
 **
 ** description		: This API Terminate this component
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
 AL_Return_t AI_PR_term ( void )
{
	AL_Return_t ret_val = AL_SUCCESS;
	al_uint8 count;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	/* Create Semaphore for the Global value */
	PR_MUTEX_LOCK(g_pr_mutex_id);

	count = g_head_node;

	while ( count < g_Init_Param.MaxNumOfReminders )
	{

		if( g_event_details[count].details.enable == al_true )
		{
			if ( AL_SUCCESS != AL_SCH_UnScheduleEvent( &g_event_details[count].sch_id))
			{
				PR_ERROR("AL_SCH_UnScheduleEvent() Failed \n");
			}
		}
		count = g_event_details[count].next_index;
	}

	if (pf_PR_GetContext != NULL)
	{
		for(count=0; count < g_Init_Param.MaxNumOfReminders; count ++)
		{
			ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
							(al_void *)(&g_event_details[count]), (al_uint32)count);
			if (ret_val != AL_SUCCESS)
			{
				PR_MUTEX_UNLOCK(g_pr_mutex_id);
				return ret_val;
			}
		}
	}
	g_head_node = g_Init_Param.MaxNumOfReminders;
	/*the time of show popmessage befor event coming.*/
	g_Init_Param.app_schd_time[0] = 0;

	/*the max number of  event.*/
	g_Init_Param.MaxNumOfReminders = 0;

	free(g_event_details);

	g_event_details = NULL;

	PR_MUTEX_UNLOCK(g_pr_mutex_id);

	if (g_pr_mutex_id)
	{
		GL_MutexDelete(g_pr_mutex_id);
		g_pr_mutex_id = al_null;
	}
	
	g_initSuccess = FALSE;

	return ret_val;

}
/************************************************************************
 ** name				:AL_PR_GetMaxNoOfReminders()
 **
 ** description		: This API returns the second that before registed event take place.
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: al_uint32 time in sec
 ************************************************************************/
al_uint8 AL_PR_GetMaxNoOfReminders(void)
{	
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return 0;
	}
	return g_Init_Param.MaxNumOfReminders;
}
/************************************************************************
 ** name				:AL_PR_NotifyTime()
 **
 ** description		: This API returns the second that before registed event take place.
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: al_uint32 time in sec
 ************************************************************************/
al_uint32 AL_PR_NotifyTime(void)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return 0;
	}
	return  g_Init_Param.app_schd_time[0];
}
/************************************************************************
 ** name				: AL_PR_Add()
 **
 ** description		: Add new reminder
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_Add( AL_PR_details_t* details , AL_SCH_sched_id_t* id)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_SCH_sched_id_t temp_sch_id = 0;
	AL_Return_t ret = AL_FAILURE;
	al_bool retvalue = al_false;
	al_uint8 total_count = 0;
	al_uint8 count = 0;
	al_uint32 CurTimeInSec = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;

	AL_Time_GetCurTimeInSecs(&CurTimeInSec);

	AL_FW_GetContextCb(&pf_PR_GetContext);

	/* check for input parameters */
	if((details == NULL)||( id == NULL ))
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	/* Reminder cannopt be added in the disable state */
	if ( details->enable == al_false )
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	/* Check if the new record can be added for the given reminder type */
	if (details->rem_type == AL_PR_SRV_REM)
	{
#if (AL_PR_MAX_NO_SRV_REMINDERS == 0)
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_SRV_REM | AL_PR_ANA_EVT_REM, &total_count);
		if( total_count >= g_Init_Param.MaxNumOfReminders )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#else
		AL_PR_GetTotal(details->db_type, details->rem_type, &total_count);
		if ( total_count >= AL_PR_MAX_NO_SRV_REMINDERS )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#endif
	} 
	else if ((details->rem_type == AL_PR_EVT_REM) ||
		(details->rem_type == AL_PR_ANA_EVT_REM))
	{

#if (AL_PR_MAX_NO_EVT_REMINDERS == 0)
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_SRV_REM | AL_PR_ANA_EVT_REM, &total_count);
		if( total_count >= g_Init_Param.MaxNumOfReminders )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#else
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_ANA_EVT_REM, &total_count);
		if ( total_count >= AL_PR_MAX_NO_EVT_REMINDERS )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#endif
	}
	else
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	if ( _AI_PR_FillDetails(details) != AL_SUCCESS )
	{
		return AL_FAILURE;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);

	retvalue = _AI_PR_CheckReminderAtTime(details->start_local_time_secs, &temp_sch_id);

	if( retvalue == al_true )
	{
		*id = temp_sch_id;
		PR_ERROR(" START TIME COLLISION!!! ");

		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_REMINDER_OVERLAP_START_TIME;
	}
/*add by kai.wang for mantis:0176702*/
	if ((details->start_local_time_secs < CurTimeInSec + AL_PR_NotifyTime()) && (details->snooze_time_secs == 0))
	{
		PR_ERROR(" no time to show pop message!!! \n");
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_REMINDER_OVERLAP_START_TIME;
	}
/*end by kai.wang*/
	if (details->rem_type == AL_PR_SRV_REM)
	{
		retvalue=_AI_PR_CheckReminderOverlapForSer(details->start_local_time_secs);
		if (retvalue == al_true)
		{
			PR_ERROR(" RECORDING TIME COLLISION!!! \n");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_START_TIME;
		}
	}

	if (details->rem_type == AL_PR_EVT_REM)
	{
		retvalue = _AI_PR_CheckReminderOverlap(details->start_local_time_secs,
			details->rem_details.event_end_time_insec);
		if (retvalue == al_true)
		{
			PR_ERROR(" RECORDING TIME COLLISION!!! ");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_START_TIME;
		}
	}

	count = _AI_PR_GetFreeNode();

	if ( count == g_Init_Param.MaxNumOfReminders )
	{
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		PR_ERROR(" NO MORE REMINDERS ARE ALLOWED\n ");

		return AL_REMINDER_SCHE_EVENT_FULL;
	}
	g_event_details[count].details.db_type = details->db_type;
	g_event_details[count].details.rem_type = details->rem_type;
	memcpy(&(g_event_details[count].details.rem_details), & (details->rem_details),
		sizeof(details->rem_details));
	g_event_details[count].details.start_local_time_secs = details->start_local_time_secs;
	g_event_details[count].details.snooze_time_secs = details->snooze_time_secs;
	g_event_details[count].details.enable = details->enable ;
	g_event_details[count].details.gmt_offset = details->gmt_offset;
	g_event_details[count].details.weekday = details->weekday;
	/*when the event isn't once, need check the start time again.*/
	if(g_event_details[count].details.snooze_time_secs != 0)
	{
		_AI_PR_ModyfiSnoozeEvent(count);
	}

	/* Shcedule the event */
	ret = _AI_PR_Schedule ( count );

	if ( ret == AL_SUCCESS )
	{
		*id = g_event_details[count].sch_id;

		_AI_PR_InsertNode(count);

		/* write to persistent memory */

		if (pf_PR_GetContext != NULL)
		{
			ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
							&g_event_details[count], count);
			if (ret != AL_SUCCESS)
			{
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return ret;
			}
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret;
}

/************************************************************************
 ** name				: AL_PR_AddEx()
 **
 ** description		: Add new reminder and get the conflicted timers
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_AddEx( AL_PR_details_t* details , AL_SCH_sched_id_t* id,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_SCH_sched_id_t temp_sch_id = 0;
	AL_Return_t ret = AL_FAILURE;
	al_bool retvalue = al_false;
	al_uint8 total_count = 0;
	al_uint8 count = 0;
	al_uint32 CurTimeInSec = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;

	AL_Time_GetCurTimeInSecs(&CurTimeInSec);

	AL_FW_GetContextCb(&pf_PR_GetContext);

	/* check for input parameters */
	if((details == NULL)||( id == NULL ))
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	/* Reminder cannopt be added in the disable state */
	if ( details->enable == al_false )
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	/* Check if the new record can be added for the given reminder type */
	if (details->rem_type == AL_PR_SRV_REM)
	{
#if (AL_PR_MAX_NO_SRV_REMINDERS == 0)
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_SRV_REM | AL_PR_ANA_EVT_REM, &total_count);
		if( total_count >= g_Init_Param.MaxNumOfReminders )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#else
		AL_PR_GetTotal(details->db_type, details->rem_type, &total_count);
		if ( total_count >= AL_PR_MAX_NO_SRV_REMINDERS )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#endif
	}
	else if ((details->rem_type == AL_PR_EVT_REM) ||
		(details->rem_type == AL_PR_ANA_EVT_REM))
	{

#if (AL_PR_MAX_NO_EVT_REMINDERS == 0)
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_SRV_REM | AL_PR_ANA_EVT_REM, &total_count);
		if( total_count >= g_Init_Param.MaxNumOfReminders )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#else
		AL_PR_GetTotal(details->db_type, AL_PR_EVT_REM | AL_PR_ANA_EVT_REM, &total_count);
		if ( total_count >= AL_PR_MAX_NO_EVT_REMINDERS )
		{
			return AL_REMINDER_SCHE_EVENT_FULL;
		}
#endif
	}
	else
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	if ( _AI_PR_FillDetails(details) != AL_SUCCESS )
	{
		return AL_FAILURE;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);

	retvalue = _AI_PR_CheckReminderAtTimeEx(details->start_local_time_secs, &temp_sch_id,ConflictTimerID, ConflictTimerNum);

	if( retvalue == al_true )
	{
		*id = temp_sch_id;
		PR_ERROR(" START TIME COLLISION!!! ");

		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_REMINDER_OVERLAP_START_TIME_WITHOTHERTIMER;
	}
/*add by kai.wang for mantis:0176702*/
	if (details->start_local_time_secs < CurTimeInSec + AL_PR_NotifyTime())
	{
		PR_ERROR(" no time to show pop message!!! \n");
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_REMINDER_OVERLAP_START_TIME;
	}
/*end by kai.wang*/
	if (details->rem_type == AL_PR_SRV_REM)
	{
		retvalue=_AI_PR_CheckReminderOverlapForSerEx(details->start_local_time_secs,ConflictTimerID, ConflictTimerNum);
		if (retvalue == al_true)
		{
			PR_ERROR(" RECORDING TIME COLLISION!!! \n");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_SRC_TIME;
		}
	}

	if (details->rem_type == AL_PR_EVT_REM)
	{
		retvalue = _AI_PR_CheckReminderOverlapEx(details->start_local_time_secs,
			details->rem_details.event_end_time_insec,ConflictTimerID, ConflictTimerNum);
		if (retvalue == al_true)
		{
			PR_ERROR(" RECORDING TIME COLLISION!!! ");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_REC_TIME;
		}
	}

	count = _AI_PR_GetFreeNode();

	if ( count == g_Init_Param.MaxNumOfReminders )
	{
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		PR_ERROR(" NO MORE REMINDERS ARE ALLOWED\n ");

		return AL_REMINDER_SCHE_EVENT_FULL;
	}
	g_event_details[count].details.db_type = details->db_type;
	g_event_details[count].details.rem_type = details->rem_type;
	memcpy(&(g_event_details[count].details.rem_details), & (details->rem_details),
		sizeof(details->rem_details));
	g_event_details[count].details.start_local_time_secs = details->start_local_time_secs;
	g_event_details[count].details.snooze_time_secs = details->snooze_time_secs;
	g_event_details[count].details.enable = details->enable ;
	g_event_details[count].details.gmt_offset = details->gmt_offset;

	/* Shcedule the event */
	ret = _AI_PR_Schedule ( count );

	if ( ret == AL_SUCCESS )
	{
		*id = g_event_details[count].sch_id;

		_AI_PR_InsertNode(count);

		/* write to persistent memory */

		if (pf_PR_GetContext != NULL)
		{
			ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
							&g_event_details[count], count);
			if (ret != AL_SUCCESS)
			{
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return ret;
			}
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret;
}

/************************************************************************
 ** name				: AL_PR_Delete()
 **
 ** description			: This API Delete this reminder
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type			: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_Delete( AL_SCH_sched_id_t id)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 prev_index, count;
	AL_Return_t ret;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	/* check for input parameter */
	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* unschedule the event and remove from the list*/
	for( count = g_head_node, prev_index= g_Init_Param.MaxNumOfReminders;
		count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index )
	{
		//g_event_details[count].details.sch_id,*id);
		if ( (g_event_details[count].sch_id == id )
			&& (g_event_details[count].details.occupied == al_true ))
		{
			if (g_event_details[count].details.enable == al_true )
			{
				if ( AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) !=
					AL_SUCCESS)
				{
					PR_ERROR("Error to delete the schedule\n\n");
				}
			}

			/*** DELETE THE NODE ***/
			if ( prev_index >= g_Init_Param.MaxNumOfReminders )
			{
				g_head_node = g_event_details[count].next_index;
			}
			else
			{
				g_event_details[prev_index].next_index = g_event_details[count].next_index;
			}
            memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
			g_event_details[count].details.occupied = al_false;
			g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;

			/* write to persistent memory */
			if (pf_PR_GetContext != NULL)
			{
				ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
								(al_void *)(&g_event_details[count]), (al_uint32)count);
				if (ret != AL_SUCCESS)
				{
					PR_MUTEX_UNLOCK ( g_pr_mutex_id );
					return ret;
				}
			}
			break;
		}
		prev_index = count ;
	}


	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	if ( count  >= g_Init_Param.MaxNumOfReminders)
	{
		return AL_FAILURE;
	}

	return AL_SUCCESS;
}

/************************************************************************
 ** name				: AL_PR_EnableStatus()
 **
 ** description		: This API modifies Then enable disable status.
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_EnableStatus(AL_SCH_sched_id_t id, al_bool enable_rem)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
	AL_Return_t ret_val = AL_FAILURE;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* copy the details to internal structure */
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if(( g_event_details[count].sch_id == id) && (g_event_details[count].details.occupied == al_true ))
		{
			if ( g_event_details[count].details.enable != enable_rem )
			{
				g_event_details[count].details.enable = enable_rem;
				if( g_event_details[count].details.enable == al_false )
				{
					if (AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
					{
						PR_ERROR("Error to delete the schedule\n\n");
					}
				}
				else
				{
					if (AL_SUCCESS != _AI_PR_Schedule ( count ))
					{
						PR_ERROR("_AI_PR_Schedule error !!!!!!\n");
					}
				}
				/* write to persistent memory */
				if (pf_PR_GetContext != NULL)
				{
					ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
									&g_event_details[count], count);
					if (ret_val != AL_SUCCESS)
					{
						PR_MUTEX_UNLOCK ( g_pr_mutex_id );
						return ret_val;
					}
				}
			}
			ret_val = AL_SUCCESS;
			break;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret_val;
}
/************************************************************************
 ** name				: AL_PR_SetAllStatus()
 **
 ** description		: This API modifies Then enable disable status.
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_SetAllStatus(al_bool enable_rem)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
	AL_Return_t ret;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* copy the details to internal structure */
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if(g_event_details[count].details.occupied == al_true )
		{
			if ( g_event_details[count].details.enable != enable_rem )
			{
				g_event_details[count].details.enable = enable_rem;
				if( g_event_details[count].details.enable == al_false )
				{
					if (AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
					{
						PR_ERROR("Error to delete the schedule\n\n");
					}
				}
				else
				{
					_AI_PR_Schedule ( count );
				}
				/* write to persistent memory */
				if (pf_PR_GetContext != NULL)
				{
					ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
									&g_event_details[count], count);
					if (ret != AL_SUCCESS)
					{
						PR_MUTEX_UNLOCK ( g_pr_mutex_id );
						return ret;
					}
				}

			}
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return AL_SUCCESS;
}

/************************************************************************
 ** name				: AL_PR_Modify()
 **
 ** description		: This API modifies the scheduled event with new information
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_Modify(AL_PR_details_t *details ,AL_SCH_sched_id_t id)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_Return_t ret = AL_FAILURE;
	al_bool retvalue = 0;
	AL_SCH_sched_id_t temp_sch_id = 0;
	al_uint8 offset = 0;
	al_uint8 prev_offset = 0;
	al_uint32 CurTimeInSec = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;

	AL_Time_GetCurTimeInSecs(&CurTimeInSec);
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_DEBUG("----------------------------------\n");
	PR_DEBUG("hdl =========   %x\n",details->rem_details.handle);
	PR_DEBUG("start time =========   %d\n",details->start_local_time_secs);
	PR_DEBUG("end  time =========   %d\n",details->rem_details.event_end_time_insec);
	PR_DEBUG("offse =========   %d\n",details->gmt_offset);
	PR_DEBUG("----------------------------------\n");
	if ( details == NULL )
	{
		PR_ERROR("Invalid Input Parameters\n");
		return AL_INVALID_PARAM;
	}

	if ( _AI_PR_FillDetails(details) != AL_SUCCESS )
	{
		return AL_FAILURE;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);


	prev_offset = g_Init_Param.MaxNumOfReminders;

	for( offset = g_head_node; offset< g_Init_Param.MaxNumOfReminders;
			offset = g_event_details[offset].next_index)
	{
		if(g_event_details[offset].sch_id == id)
		{
			break;
		}
		prev_offset = offset;
	}

	if(offset >= g_Init_Param.MaxNumOfReminders)
	{
		PR_ERROR("NO SUCH SCH_ID !!! \n");
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	if ( details->enable )
	{
		retvalue = _AI_PR_CheckReminderAtTime(details ->start_local_time_secs, &temp_sch_id);
		if( retvalue == al_true )
		{
			if(id != temp_sch_id)
			{
				PR_ERROR(" TIME COLLISION!!! ");
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_START_TIME;
			}
		}

		/*add by kai.wang  for mantis:0176702*/
		if (details->start_local_time_secs < CurTimeInSec + AL_PR_NotifyTime())
		{
			PR_ERROR(" no time to show pop message!!! \n");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_START_TIME;
		}
		/*end by kai.wang*/

		/*add by kai.wang for mantis:0174006*/
		g_event_details[offset].details.enable = al_false;

		if (details->rem_type == AL_PR_SRV_REM)
		{
			retvalue=_AI_PR_CheckReminderOverlapForSer(details->start_local_time_secs);
			if (retvalue == al_true)
			{
				PR_ERROR(" RECORDING TIME COLLISION!!! ===========================\n");

				/*add by kai.wang for mantis:0174006*/
				g_event_details[offset].details.enable = al_true;
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_START_TIME;
			}
		}

		if (details->rem_type == AL_PR_EVT_REM)
		{
			retvalue = _AI_PR_CheckReminderOverlap(details->start_local_time_secs,
				details->rem_details.event_end_time_insec);
			if (retvalue == al_true)
			{
				PR_ERROR(" RECORDING TIME COLLISION!!! ");

				/*add by kai.wang for mantis:0174006*/
				g_event_details[offset].details.enable = al_true;
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_START_TIME;
			}
		}

	}

	/* Remove the node */
	if ( prev_offset == g_Init_Param.MaxNumOfReminders)
	{
		/* Remove the head node */
		g_head_node = g_event_details[offset].next_index;
	}
	else
	{
		g_event_details[prev_offset].next_index = g_event_details[offset].next_index;
	}

	g_event_details[offset].details.rem_type = details->rem_type;
	memcpy(&(g_event_details[offset].details.rem_details), &(details->rem_details), sizeof(details->rem_details));

	g_event_details[offset].details.start_local_time_secs = details->start_local_time_secs;
	g_event_details[offset].details.snooze_time_secs = details->snooze_time_secs;
	g_event_details[offset].details.gmt_offset = details->gmt_offset;
	g_event_details[offset].details.weekday = details->weekday;

	if ( (details->enable == al_false) &&  (g_event_details[offset].details.enable == al_true ))
	{
		AL_SCH_UnScheduleEvent(&g_event_details[offset].sch_id);
	}
	g_event_details[offset].details.enable = details->enable;

	/* Shcedule the event */
	ret = _AI_PR_Reschedule ( offset );
	if ( ret == AL_SUCCESS )
	{
		//id = g_event_details[offset].sch_id;
	}
	else
	{
		g_event_details[offset].details.enable = al_false;
	}

	/* Insert the node */
	_AI_PR_InsertNode(offset);

	if (pf_PR_GetContext != al_null)
	{
		ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
						&g_event_details[offset], offset);
		if (ret != AL_SUCCESS)
		{
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return ret;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret;
}

/************************************************************************
 ** name				: AL_PR_ModifyEx()
 **
 ** description 	: This API modifies the scheduled event with new information
 ** 				: and get the conflicted timers
 **
 ** input parameters	: none
 **
 ** output parameters	:	none
 **
 ** return type 	: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_ModifyEx(AL_PR_details_t *details ,AL_SCH_sched_id_t id,AL_SCH_sched_id_t* ConflictTimerID, UINT8* ConflictTimerNum)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_Return_t ret = AL_FAILURE;
	al_bool retvalue = FALSE;
	AL_SCH_sched_id_t temp_sch_id = 0;
	al_uint8 offset = 0;
	al_uint8 prev_offset = 0;
	al_uint32 CurTimeInSec = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = al_null;

	AL_Time_GetCurTimeInSecs(&CurTimeInSec);
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_DEBUG("----------------------------------\n");
	PR_DEBUG("hdl =========   %x\n",details->rem_details.handle);
	PR_DEBUG("start time =========   %d\n",details->start_local_time_secs);
	PR_DEBUG("end  time =========   %d\n",details->rem_details.event_end_time_insec);
	PR_DEBUG("offse =========   %d\n",details->gmt_offset);
	PR_DEBUG("----------------------------------\n");
	if ( details == al_null )
	{
		PR_ERROR("Invalid Input Parameters\n");
		return AL_INVALID_PARAM;
	}

	if ( _AI_PR_FillDetails(details) != AL_SUCCESS )
	{
		return AL_FAILURE;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);


	prev_offset = g_Init_Param.MaxNumOfReminders;

	for( offset = g_head_node; offset< g_Init_Param.MaxNumOfReminders;
			offset = g_event_details[offset].next_index)
	{
		if(g_event_details[offset].sch_id == id)
		{
			break;
		}
		prev_offset = offset;
	}

	if(offset >= g_Init_Param.MaxNumOfReminders)
	{
		PR_ERROR("NO SUCH SCH_ID !!! \n");
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	if ( details->enable )
	{
		retvalue = _AI_PR_CheckReminderAtTimeEx(details ->start_local_time_secs, &temp_sch_id,ConflictTimerID, ConflictTimerNum);
		if( retvalue == al_true )
		{
			if(id != temp_sch_id)
			{
				PR_ERROR(" TIME COLLISION!!! ");
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_START_TIME_WITHOTHERTIMER;
			}
		}

		/*add by kai.wang  for mantis:0176702*/
		if (details->start_local_time_secs < CurTimeInSec + AL_PR_NotifyTime())
		{
			PR_ERROR(" no time to show pop message!!! \n");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_OVERLAP_START_TIME;
		}
		/*end by kai.wang*/

		/*add by kai.wang for mantis:0174006*/
		g_event_details[offset].details.enable = al_false;

		if (details->rem_type == AL_PR_SRV_REM)
		{
			retvalue=_AI_PR_CheckReminderOverlapForSerEx(details->start_local_time_secs,ConflictTimerID, ConflictTimerNum);
			if (retvalue == al_true)
			{
				PR_ERROR(" RECORDING TIME COLLISION!!! ===========================\n");

				/*add by kai.wang for mantis:0174006*/
				g_event_details[offset].details.enable = al_true;
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_SRC_TIME;
			}
		}

		if (details->rem_type == AL_PR_EVT_REM)
		{
			retvalue = _AI_PR_CheckReminderOverlapEx(details->start_local_time_secs,
				details->rem_details.event_end_time_insec,ConflictTimerID, ConflictTimerNum);
			if (retvalue == al_true)
			{
				PR_ERROR(" RECORDING TIME COLLISION!!! ");

				/*add by kai.wang for mantis:0174006*/
				g_event_details[offset].details.enable = al_true;
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return AL_REMINDER_OVERLAP_REC_TIME;
			}
		}

	}

	/* Remove the node */
	if ( prev_offset == g_Init_Param.MaxNumOfReminders)
	{
		/* Remove the head node */
		g_head_node = g_event_details[offset].next_index;
	}
	else
	{
		g_event_details[prev_offset].next_index = g_event_details[offset].next_index;
	}

	g_event_details[offset].details.rem_type = details->rem_type;
	memcpy(&(g_event_details[offset].details.rem_details), &(details->rem_details), sizeof(details->rem_details));

	g_event_details[offset].details.start_local_time_secs = details->start_local_time_secs;
	g_event_details[offset].details.snooze_time_secs = details->snooze_time_secs;
	g_event_details[offset].details.gmt_offset = details->gmt_offset;
	g_event_details[offset].details.weekday = details->weekday;

	if ( (details->enable == al_false) &&  (g_event_details[offset].details.enable == al_true ))
	{
		AL_SCH_UnScheduleEvent(&g_event_details[offset].sch_id);
	}
	g_event_details[offset].details.enable = details->enable;

	/* Shcedule the event */
	ret = _AI_PR_Reschedule ( offset );
	if ( ret == AL_SUCCESS )
	{
		//id = g_event_details[offset].sch_id;
	}
	else
	{
		g_event_details[offset].details.enable = al_false;
	}

	/* Insert the node */
	_AI_PR_InsertNode(offset);

	if (pf_PR_GetContext != al_null)
	{
		ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
						(al_void *)(&g_event_details[offset]), (al_uint32)offset);
		if (ret != AL_SUCCESS)
		{
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return ret;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret;
}

/************************************************************************
 ** name				: AL_GetByOffset
 **
 ** description		: This API Terminate this component
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_GetByOffset ( al_uint8 offset,AL_PR_details_t *details)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	AL_Return_t ret_val = AL_FAILURE;

	/* check for invalid parameter */
	if( (details == al_null ) || (offset > g_Init_Param.MaxNumOfReminders))
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* copy the details to internal structure */
	if( g_event_details[offset].details.occupied == al_true )
    {
        details->db_type = g_event_details[offset].details.db_type;
		details->rem_type = g_event_details[offset].details.rem_type;
		memcpy(&(details->rem_details),
			&(g_event_details[offset].details.rem_details), sizeof( AL_PR_schedule_details_t));
		details->sch_id = g_event_details[offset].sch_id;
		details->start_local_time_secs = g_event_details[offset].details.start_local_time_secs;
		details->snooze_time_secs = g_event_details[offset].details.snooze_time_secs;
		//details->index = g_event_details[offset].details.index;
		details->enable = g_event_details[offset].details.enable;
		details->gmt_offset = g_event_details[offset].details.gmt_offset;

		ret_val = AL_SUCCESS;
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret_val;
}

/************************************************************************
 ** name				: AL_PR_GetById(AL_SCH_sched_id_t *id,AL_PR_details_t details)
 **
 ** description		: This API Terminate this component
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_GetById(AL_SCH_sched_id_t id , AL_PR_details_t *details)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
	AL_Return_t ret_val = AL_FAILURE;

	/* check for invalid parameter */
	if(details == NULL)
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* copy the details to internal structure */
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if(( g_event_details[count].sch_id == id) && (g_event_details[count].details.occupied == al_true )&&(g_event_details[count].details.enable == al_true))
		{
            details->db_type = g_event_details[count].details.db_type;
			details->rem_type =  g_event_details[count].details.rem_type;
			memcpy(&(details->rem_details),
				&(g_event_details[count].details.rem_details),
				sizeof(AL_PR_schedule_details_t));
			details->sch_id = g_event_details[count].sch_id;
			details->start_local_time_secs = g_event_details[count].details.start_local_time_secs;
			details->snooze_time_secs = g_event_details[count].details.snooze_time_secs;
			//details->index = g_event_details[count].details.index;
			details->enable = g_event_details[count].details.enable;
			details->gmt_offset = g_event_details[count].details.gmt_offset;
			details->weekday = 	g_event_details[count].details.weekday;
			ret_val = AL_SUCCESS;
			break;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret_val;
}

/************************************************************************
 ** name				: AL_PR_GetTotal
 **
 ** description		: This API Terminate this component
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_GetTotal (AL_DB_EDBType_t db_type, AL_PR_type_t rem_type, al_uint8* total_count)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;

	/* check for invalid parameter */
	if( total_count == NULL )
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}


	PR_MUTEX_LOCK(g_pr_mutex_id);

	for( count = g_head_node, *total_count= 0; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if( (g_event_details[count].details.rem_type & rem_type) && g_event_details[count].details.db_type == db_type)
		{
			(*total_count)++;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return AL_SUCCESS;
}
/************************************************************************
 ** name				: AL_PR_Get(AL_SCH_sched_id_t *id,AL_PR_details_t details)
 **
 ** description		: This API Terminate this component
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_Get (AL_DB_EDBType_t db_type, AL_PR_record_type_t req_type, AL_PR_type_t rem_type,
		AL_SCH_sched_id_t ref_id , AL_SCH_sched_id_t *ret_id)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;

	if (ret_id == NULL)
	{
		PR_ERROR(" INVALID INPUT PARAMETER\n");
		return AL_INVALID_PARAM;
	}

 	*ret_id = g_Init_Param.MaxNumOfReminders;

	PR_MUTEX_LOCK(g_pr_mutex_id);
	count = g_head_node;
	//prev_index = g_Init_Param.MaxNumOfReminders ;
	if ( req_type == AL_PR_REC_FIRST )
	{
		while( count < g_Init_Param.MaxNumOfReminders )
		{
			if (g_event_details[count].details.rem_type & rem_type)
			{
				if (g_event_details[count].details.db_type == db_type)
				{
					*ret_id = g_event_details[count].sch_id;
					break;
				}
			}
			count = g_event_details[count].next_index;
		}
	}
	else if (req_type == AL_PR_REC_LAST)
	{
		while( count < g_Init_Param.MaxNumOfReminders )
		{
			if (g_event_details[count].details.rem_type & rem_type)
			{
				if (g_event_details[count].details.db_type == db_type)
				{
					*ret_id = g_event_details[count].sch_id;
				}
			}
			count = g_event_details[count].next_index;
		}
	}
	else if (req_type == AL_PR_REC_NEXT)
	{
		while( count < g_Init_Param.MaxNumOfReminders )
		{
			if (g_event_details[count].sch_id == ref_id)
			{
				break;
			}
			count = g_event_details[count].next_index;
		}

		if ( count >= g_Init_Param.MaxNumOfReminders )
		{
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_FAILURE;
		}

		count = g_event_details[count].next_index;

		while(count < g_Init_Param.MaxNumOfReminders)
		{
			if (g_event_details[count].details.rem_type & rem_type)
			{
				if (g_event_details[count].details.db_type == db_type)
				{
					*ret_id = g_event_details[count].sch_id;
					break;
				}
			}
			count = g_event_details[count].next_index;
		}
	}
	else if (req_type == AL_PR_REC_PREV)
	{
		al_uint8 pre_count = g_Init_Param.MaxNumOfReminders;
		al_uint8 pos = 0;

		while( count < g_Init_Param.MaxNumOfReminders )
		{
			if (g_event_details[count].sch_id == ref_id)
			{
				break;
			}
			pos++;
			count = g_event_details[count].next_index;
		}

		if ( count >= g_Init_Param.MaxNumOfReminders )
		{
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_FAILURE;
		}

		count = g_head_node;

		while( count < g_Init_Param.MaxNumOfReminders )
		{
			if (g_event_details[count].sch_id == ref_id)
			{
				if (count == g_head_node)
				{
					break;
				}
				if (pre_count != g_Init_Param.MaxNumOfReminders && pre_count != count)
				{
					*ret_id = g_event_details[pre_count].sch_id;
					break;
				}
			}
			if (g_event_details[count].details.rem_type & rem_type)
			{
				if (g_event_details[count].details.db_type == db_type)
				{
					pre_count = count;
				}
			}
			if (pos == 0)
			{
				break;
			}
			pos--;
			count = g_event_details[count].next_index;
		}

	}

	if ( count >= g_Init_Param.MaxNumOfReminders )
	{
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return AL_SUCCESS;
}

/************************************************************************
 ** name				:APP_Data_PR_delete_all_sch()
 **
 ** description		: This API delete all the schedule for the Program reminder
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
 AL_Return_t AL_PR_DeleteAllSch (AL_DB_EDBType_t db_type,  AL_PR_type_t rem_type )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count, prev_node_index;
	AL_Return_t ret;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_MUTEX_LOCK(g_pr_mutex_id);

	count = g_head_node;
	prev_node_index = g_Init_Param.MaxNumOfReminders;

	while ( count < g_Init_Param.MaxNumOfReminders )
	{

		if ( (g_event_details[count].details.rem_type & rem_type) &&  g_event_details[count].details.db_type == db_type)
		{
			if ( g_event_details[count].details.enable == al_true )
			{
				if ( AL_SUCCESS != AL_SCH_UnScheduleEvent( &g_event_details[count].sch_id))
				{
					PR_ERROR("AL_SCH_UnScheduleEvent() Failed \n");
				}
			}
			if( count == g_head_node)
			{
				g_head_node = g_event_details[count].next_index;
			}
			else
			{
				g_event_details[prev_node_index].next_index= g_event_details[count].next_index;
			}
            memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
			g_event_details[count].details.occupied= al_false;
		}
		else
		{
			prev_node_index = count;
		}
		/* Write to the data persistent memory */
		if (pf_PR_GetContext != NULL)
		{
			ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
							(al_void *)(&g_event_details[count]), (al_uint32)count);
			if (ret != AL_SUCCESS)
			{
				PR_MUTEX_UNLOCK ( g_pr_mutex_id );
				return ret;
			}
		}

		count = g_event_details[count].next_index;
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return AL_SUCCESS;
}

/************************************************************************
 ** name				:AL_PR_DefaultSetup()
 **
 ** description		: This API perform default setup.
 **
 ** input parameters	: none
 **
 ** output parameters	:   none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
 AL_Return_t AL_PR_DefaultSetup( AL_DB_EDBType_t db_type )
{
	return ( AL_PR_DeleteAllSch(db_type, AL_PR_SRV_REM |AL_PR_EVT_REM | AL_PR_ANA_EVT_REM ));
}

/************************************************************************
 ** name			:AL_PR_IsEvtSch()
 **
 ** description		: This API determines if a particular event is scheduled
 **						or not
 **
 ** input parameters	:evt_id - event ID of the event to be checked
 **
 ** output parameters	:is_sch - boolean value stating if the event is
 **						 scheduled or not
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_IsEvtSch(al_uint16 evt_id, al_bool *is_sch, AL_SCH_sched_id_t *ret_id)
{
#if 0
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
	//AIEC_addnl_evnt_t evt_addnl_details;
	AL_Return_t ret_val = AL_FAILURE;
	AL_DB_EDBType_t handle, stored_handle;
	AL_PR_schedule_details_t *rem_details;

	/* check for input parameters */
	if((evt_id == NULL )||( is_sch == NULL )){
		PR_ERROR((" Invalid Parameter \n "));
		return AL_INVALID_PARAM;
	}

	*is_sch = al_false;
	PR_MUTEX_LOCK(g_pr_mutex_id);

	if(AL_SUCCESS != AIEC_get_addnl_event_details(evt_id , &evt_addnl_details)){
		PR_ERROR((" FAILED TO GET THE ADDITIONAL INFO OF THE EVENT"));
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	if( AL_SUCCESS != AFW_get_service_of_event_id( evt_id, &handle)){
		PR_ERROR((" FAILED TO GET EVENT SERVICE ID"));
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders;
									count = g_event_details[count].next_index){

		if( g_event_details[count].details.enable == al_false ){
			continue;
		}

		rem_details = &(g_event_details[count].details.rem_details);

		if( AL_SUCCESS !=
			AFW_get_service_of_event_id( &rem_details->event_sch_details.event_id,
										&stored_handle)){
			PR_ERROR((" FAILED TO GET EVENT SERVICE ID"));
			continue;
		}

		if((g_event_details[count].details.occupied == al_true)  &&
			(g_event_details[count].details.rem_type == AL_PR_EVT_REM) &&
			(rem_details->event_sch_details.event_no == evt_addnl_details.evt_id) &&
			(AISRV_is_service_same(&srv_id, &stored_srv_id)== al_true)){

				*is_sch = al_true;
			*ret_id =g_event_details[count].sch_id;
			ret_val = AL_SUCCESS;

		}

	}
	PR_MUTEX_UNLOCK ( g_pr_mutex_id );
#endif
	return AL_SUCCESS;
}

/************************************************************************
 ** name			:AL_PR_IsSrvSch()
 **
 ** description		: This API determines if a particular service is scheduled
 **						or not
 **
 ** input parameters	:handle - event ID of the event to be checked
 **
 ** output parameters	:is_sch - boolean value stating if the event is
 **						 scheduled or not
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_IsSrvSch(AL_RecHandle_t handle, al_bool *is_sch, AL_SCH_sched_id_t *ret_id, al_uint32 start_time)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;

	/* check for input parameters */
	if( is_sch == NULL)
	{
		PR_ERROR(" Invalid Parameter \n ");
		return AL_INVALID_PARAM;
	}

	*is_sch = al_false;
	PR_MUTEX_LOCK(g_pr_mutex_id);

	for ( count = g_head_node ; (count < g_Init_Param.MaxNumOfReminders); count = g_event_details[count].next_index)
	{
		if ((g_event_details[count].details.occupied == al_true )
			&& ( g_event_details[count].details.rem_type == AL_PR_SRV_REM)
			&& (g_event_details[count].details.enable == al_true))
		{
			if (g_event_details[count].details.rem_details.handle ==  handle
				&& (g_event_details[count].details.start_local_time_secs == start_time))
			{
					*is_sch = al_true;
					*ret_id =g_event_details[count].sch_id;
					break;
			}
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return AL_SUCCESS;

}

/************************************************************************
 ** name			:AI_PR_HandleTrigger()
 **
 ** description		: Handle the remider status after the trigger.
 **
 ** input parameters	:id - Schedular id
 **
 ** output parameters	:None
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AI_PR_HandleTrigger( AL_SCH_sched_id_t id )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count = 0;
	al_uint32 curr_loc_time = 0;
	AL_Return_t ret_val = AL_FAILURE;
	AL_SCH_details_t sch_details;
	//AIEC_event_t event_id;
	//AL_RecHandle_t handle;

	PR_MUTEX_LOCK(g_pr_mutex_id);

	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if(( g_event_details[count].sch_id == id) && (g_event_details[count].details.occupied == al_true ))
		{
			ret_val = AL_SUCCESS;

			/* Check if Event is expired */
			if(AL_FAILURE!= AL_Time_GetCurTimeInSecs(&curr_loc_time))
			{
				if((curr_loc_time) >= (g_event_details[count].details.start_local_time_secs ))
				{
					ret_val = AL_REMINDER_EVENT_EXPIRED;
				}
			}

			/* Check if Event Exits in for the service */
			if( (ret_val == AL_SUCCESS ) && (g_event_details[count].details.rem_type == AL_PR_EVT_REM))
			{
				/* check validaton of the event */
				#if 0
				if(AL_SUCCESS !=
					AFW_get_service_of_event_id(&g_event_details[count].details.rem_details.event_sch_details.event_id,
												&handle))
				{
					PR_ERROR(("NO SUCH SRV ID\n"));
					ret_val = AL_REMINDER_EVENT_NOT_PRESENT;
				}
				#endif
				#if 0
				if( ret_val == AL_SUCCESS)
				{
					ret_val =  AIEC_get_eventid_of_num(&handle,
											g_event_details[count].details.rem_details.event_sch_details.event_no,
											&event_id);
					if( ret_val != AL_SUCCESS )
					{
						PR_ERROR(("NO SUCH EVENT NO\n"));
						ret_val = AL_REMINDER_EVENT_NOT_PRESENT;
					}
					else
					{
						/* Update the event id */
						memcpy( &(g_event_details[count].details.rem_details.event_id), &event_id, sizeof(event_id));
					}
				}
				#endif
			}

			/* if Event is of the repeat type then update the time */
			if(AL_SUCCESS != AL_SCH_GetScheduleDetails(&g_event_details[count].sch_id, &sch_details))
			{
				PR_ERROR(" Failed to get Schedule details \n ");
			}
			else
			{
				g_event_details[count].details.start_local_time_secs = sch_details.sch_time;

				if (g_event_details[count].details.rem_type == AL_PR_EVT_REM)
				{
					g_event_details[count].details.rem_details.event_end_time_insec +=
						g_event_details[count].details.snooze_time_secs;
				}
			}
			break;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret_val;
}

/************************************************************************
 ** name			:AI_PR_HandleAction()
 **
 ** description		: Handle the whether reminder should be kept or removed.
 **
 ** input parameters	:id - Schedular id
 **
 ** output parameters	:None.
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AI_PR_HandleAction( AL_SCH_sched_id_t id )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
#ifndef KEEP_EXPIRE_REM
	al_uint8 prev_index= g_Init_Param.MaxNumOfReminders;
#endif
	AL_Return_t ret_val= AL_FAILURE;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_MUTEX_LOCK(g_pr_mutex_id);

	for ( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if (( g_event_details[count].sch_id == id)
			&& (g_event_details[count].details.occupied == al_true ))
		{
			ret_val = AL_SUCCESS;
			if(g_event_details[count].details.snooze_time_secs == 0)
			{
#ifdef KEEP_EXPIRE_REM
				g_event_details[count].details.enable = al_false;
#else
				/*** DELETE THE NODE ***/
				if ( prev_index >= g_Init_Param.MaxNumOfReminders )
				{
					g_head_node = g_event_details[count].next_index;
				}
				else
				{
					g_event_details[prev_index].next_index = g_event_details[count].next_index ;
				}
				g_event_details[count].details.occupied = al_false;
				g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;
#endif
				/* write to persistent memory */
				if (pf_PR_GetContext != NULL)
				{
					ret_val = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
									(al_void *)(&g_event_details[count]), (al_uint32)count);
					if (ret_val != AL_SUCCESS)
					{
						PR_MUTEX_UNLOCK ( g_pr_mutex_id );
						return ret_val;
					}
				}
			}
			break;
		}
#ifndef KEEP_EXPIRE_REM
		prev_index = count ;
#endif
}
	PR_MUTEX_UNLOCK ( g_pr_mutex_id );
	return ret_val;
}

/************************************************************************
 ** name			:AL_PR_Update()
 **
 ** description		: Handle the whether reminder should be kept or removed for every reminder.
 **
 ** input parameters	:None
 **
 ** output parameters	:None.
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AL_PR_Update(al_int32 time_diff, al_uint32 new_time)
{
	printf("\n=====[%s] diff[%d] new[%d] offset[%d]=====\n",
		__FUNCTION__,time_diff,new_time,AL_Time_GetGMTOffset()/1800);
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}
	al_uint8 prev_index, count, index;
	AL_Return_t ret_val= AL_FAILURE;
	al_uint32 curr_loc_time = 0;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;
	AL_Return_t ret;

	AL_FW_GetContextCb(&pf_PR_GetContext);
	PR_MUTEX_LOCK(g_pr_mutex_id);
	for (index = 0; index < g_Init_Param.MaxNumOfReminders; index++)
	{
		for (count = g_head_node, prev_index= g_Init_Param.MaxNumOfReminders;
			count < g_Init_Param.MaxNumOfReminders;
			count = g_event_details[count].next_index)
		{
    		if (g_event_details[count].details.occupied == al_true)
			{
	   			if (g_event_details[index].details.start_local_time_secs
                    == g_event_details[count].details.start_local_time_secs)
    			{
					ret_val = AL_SUCCESS;
					/* time_diff == 0 indicates the first time we get system time from TOT or TDT */
					if ((AI_Time_GetTimeFristPowerON() == FALSE)
                        && (new_time != 0)
                        && (g_event_details[count].details.start_local_time_secs - g_event_details[count].details.gmt_offset*1800
						    - g_Init_Param.app_schd_time[0] < new_time))
					{
						if (g_event_details[count].details.snooze_time_secs == 0)
						{
							ret_val = AL_REMINDER_EVENT_EXPIRED;
						}
						else
						{
						    g_event_details[count].details.start_local_time_secs =
                                g_event_details[count].details.start_local_time_secs - (g_event_details[count].details.gmt_offset*1800)
                                + AL_Time_GetGMTOffset();
							g_event_details[count].details.rem_details.event_end_time_insec =
                                g_event_details[count].details.rem_details.event_end_time_insec - (g_event_details[count].details.gmt_offset*1800)
                                + AL_Time_GetGMTOffset();
                            g_event_details[count].details.gmt_offset = AL_Time_GetGMTOffset()/1800;
							_AI_PR_ModyfiSnoozeEvent(count);
						}
					}
                    else if(AI_Time_GetTimeFristPowerON() == FALSE)
                    {
						if (time_diff == 0)
						{
							g_event_details[count].details.start_local_time_secs =
	                            g_event_details[count].details.start_local_time_secs - (g_event_details[count].details.gmt_offset*1800)
	                            + AL_Time_GetGMTOffset();
	                        g_event_details[count].details.rem_details.event_end_time_insec =
	                            g_event_details[count].details.rem_details.event_end_time_insec - (g_event_details[count].details.gmt_offset*1800)
	                            + AL_Time_GetGMTOffset();
	                        g_event_details[count].details.gmt_offset = AL_Time_GetGMTOffset()/1800;
						}
                    }
                    g_event_details[count].details.gmt_offset = AL_Time_GetGMTOffset()/1800;

					/* Check if Event Exits in for the service */
					if ((g_event_details[count].details.rem_type == AL_PR_EVT_REM)
						|| (g_event_details[count].details.rem_type == AL_PR_SRV_REM))
					{
						if (ret_val == AL_SUCCESS)
						{
							if ( prev_index >= g_Init_Param.MaxNumOfReminders )
							{
								g_head_node = g_event_details[count].next_index;
							}
							else
							{
								g_event_details[prev_index].next_index = g_event_details[count].next_index;
							}

							g_event_details[count].details.start_local_time_secs += time_diff;
							g_event_details[count].details.rem_details.event_end_time_insec += time_diff;
							g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;

							_AI_PR_InsertNode(count);
							ret_val = _AI_PR_Reschedule (count);
							if (ret_val == AL_SCHEDULER_LAPSED
								&& g_event_details[count].details.snooze_time_secs == 0)
							{

								if (AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
								{
									PR_ERROR("Error to delete the schedule\n\n");
								}

#ifdef KEEP_EXPIRE_REM
								g_event_details[count].details.enable = al_false;
#else
								/*** DELETE THE NODE ***/
								if ( prev_index >= g_Init_Param.MaxNumOfReminders )
								{
									g_head_node = g_event_details[count].next_index;
								}
								else
								{
                                    if (count < g_head_node)
                                    {
                                        g_event_details[prev_index].next_index = g_event_details[count].next_index ;
                                        PR_DEBUG("[pr, delete normal node]%s          %d\n",__FUNCTION__,__LINE__);
                                    }
                                    else
                                    {
                                        g_head_node = g_event_details[g_head_node].next_index;
                                        PR_DEBUG("[pr, delete head node]%s            %d\n",__FUNCTION__,__LINE__);
                                    }
								}
                                memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
								g_event_details[count].details.occupied = al_false;
								g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;

#endif
							}

							if (ret_val == AL_SCHEDULER_LAPSED
								&& g_event_details[count].details.snooze_time_secs != 0)
							{
								PR_DEBUG("[snooze time is not zeor]%s		%d\n",__FUNCTION__,__LINE__);
								PR_DEBUG("enable %d,snooze is %d,start time is %d,end time is %d\n",
										g_event_details[count].details.enable,
										g_event_details[count].details.snooze_time_secs,
										g_event_details[count].details.start_local_time_secs,
										g_event_details[count].details.rem_details.event_end_time_insec);
								if (AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
								{
									PR_ERROR("Error to delete the schedule\n\n");
								}
								g_event_details[count].details.enable = al_true;
								_AI_PR_ModyfiSnoozeEvent(count);
							}
						}

						if (ret_val == AL_REMINDER_EVENT_EXPIRED)
						{
							if (g_event_details[count].details.enable == al_true )
							{
								if (AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
								{
									PR_ERROR("Error to delete the schedule\n\n");
								}
							}

							/*** DELETE THE NODE ***/
							if ( prev_index >= g_Init_Param.MaxNumOfReminders )
							{
								g_head_node = g_event_details[count].next_index;
							}
							else
							{
                                if (count < g_head_node)
                                {
                                    g_event_details[prev_index].next_index = g_event_details[count].next_index ;
                                    PR_DEBUG("[pr, delete normal node]%s          %d\n",__FUNCTION__,__LINE__);
                                }
                                else
                                {
                                    g_head_node = g_event_details[g_head_node].next_index;
                                    PR_DEBUG("[pr, delete head node]%s            %d\n",__FUNCTION__,__LINE__);
                                }
							}
                            memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
							g_event_details[count].details.occupied = al_false;
							g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;
						}
					}

					else if ((ret_val == AL_SUCCESS) &&
						((g_event_details[count].details.rem_type == AL_PR_SRV_REM)||
						(g_event_details[count].details.rem_type == AL_PR_ANA_EVT_REM)))
					{
						ret_val = _AI_PR_CheckSRVInvalid(g_event_details[count].details.rem_details.handle);

						if (ret_val != AL_SUCCESS)
						{
							ret_val = AL_REMINDER_EVENT_NOT_PRESENT;
							if (g_event_details[count].details.enable == al_true )
							{
								if (AL_SCH_UnScheduleEvent(&(g_event_details[
									count].sch_id)) != AL_SUCCESS)
								{
									PR_ERROR("Error to delete the schedule\n\n");
								}
							}
							/*** DELETE THE NODE ***/
							if ( prev_index >= g_Init_Param.MaxNumOfReminders )
							{
								g_head_node = g_event_details[count].next_index;
							}
							else
							{
                                if (count < g_head_node)
                                {
                                    g_event_details[prev_index].next_index = g_event_details[count].next_index ;
                                    PR_DEBUG("[pr, delete normal node]%s          %d\n",__FUNCTION__,__LINE__);
                                }
                                else
                                {
                                    g_head_node = g_event_details[g_head_node].next_index;
                                    PR_DEBUG("[pr, delete head node]%s            %d\n",__FUNCTION__,__LINE__);
                                }
							}
                            memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
							g_event_details[count].details.occupied = al_false;
							g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;
						}
					}

					/* Check if Event is expired */
					if (ret_val != AL_REMINDER_EVENT_NOT_PRESENT
						&& ret_val != AL_REMINDER_EVENT_EXPIRED
						&& ret_val != AL_SCHEDULER_LAPSED)
					{
						if (AL_FAILURE != AL_Time_GetCurTimeInSecs(&curr_loc_time))
						{	
							if ((curr_loc_time) >=
								(g_event_details[count].details.start_local_time_secs ))
							{
								if (g_event_details[count].details.snooze_time_secs == 0)
								{
#ifdef KEEP_EXPIRE_REM
									g_event_details[count].details.enable = al_false;
#else

									/*** DELETE THE NODE ***/
									if ( prev_index >= g_Init_Param.MaxNumOfReminders )
									{
										g_head_node = g_event_details[count].next_index;
									}
									else
									{
                                        if (count < g_head_node)
                                        {
                                            g_event_details[prev_index].next_index = g_event_details[count].next_index ;
                                            PR_DEBUG("[pr, delete normal node]%s          %d\n",__FUNCTION__,__LINE__);
                                        }
                                        else
                                        {
                                            g_head_node = g_event_details[g_head_node].next_index;
                                            PR_DEBUG("[pr, delete head node]%s            %d\n",__FUNCTION__,__LINE__);
                                        }
									}
                                    memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
									g_event_details[count].details.occupied = al_false;
									g_event_details[count].next_index = g_Init_Param.MaxNumOfReminders;
#endif
								}
							}
						}
					}
					/* write to persistent memory */
					if (pf_PR_GetContext != NULL)
					{
						ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
										(al_void *)(&g_event_details[count]), (al_uint32)count);
						if (ret != AL_SUCCESS)
						{
							PR_MUTEX_UNLOCK ( g_pr_mutex_id );
							return ret;
						}
					}
                    break;
				}
				//break;
			}
			prev_index = count ;
		}
	}
	PR_MUTEX_UNLOCK ( g_pr_mutex_id );

	return ret_val;

}


/************************************************************************
 ** name				: AL_PR_CheckEvtDetails()
 **
 ** description			: API gets the cdbi event id to the event id
 **
 ** input parameters	: AIEC_event_t(Event), AIEC_event_details_t(event details)
 **
 ** output parameters	: None
 **
 ** return type			: SdUCCESS or FAILURE
 ************************************************************************/
AL_Return_t AI_PR_CheckEvtDetails(AL_SCH_sched_id_t id )
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count;
	AL_Return_t  ret_val= AL_SUCCESS;
	//al_uint16 event_id;

	PR_MUTEX_LOCK(g_pr_mutex_id);

	/* get the event number stored from the sch_id */
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if(g_event_details[count].sch_id == id)
		{
			break;
		}
	}
	if (count == g_Init_Param.MaxNumOfReminders)
	{
		PR_ERROR("NO SUCH SCH ID\n");
		PR_MUTEX_UNLOCK ( g_pr_mutex_id );
		return AL_FAILURE;
	}

	if(g_event_details[count].details.rem_type == AL_PR_EVT_REM)
	{
		if(AL_SUCCESS != _AI_PR_CheckSRVInvalid(g_event_details[count].details.rem_details.handle))
		{
			PR_ERROR("NO SUCH SRV ID\n");
			PR_MUTEX_UNLOCK ( g_pr_mutex_id );
			return AL_REMINDER_SRV_NOT_PRESENT;
		}
		/* Here we should check the validation of the event id */
		//ret_val = AIEC_get_eventid_of_num(&handle,
		//							g_event_details[count].details.rem_details.event_sch_details.event_no,
		//							&event_id);
		#if 0
		AL_DB_EDBType_t DBType;
		AL_DB_ERecordType_t RecordType;
		AL_DB_Service_Info_t SerInfor;
		al_uint16 net_id;
		al_uint16 trans_id;
		al_uint16 serv_id;
		memset(&SerInfor, 0, sizeof(AL_DB_Service_Info_t));

		AL_DB_GetRecordType(g_event_details[count].details.rem_details.handle, &DBType, &RecordType);
		AL_DB_QueryRecordInfor(DBType, RecordType, g_event_details[count].details.rem_details.handle, &SerInfor);
		AL_Event_GetEventHdlByStartTime(DBType,
			net_id, trans_id, serv_id,
			AL_Time_t * event_start_time, al_uint32 duration, al_uint16 events_req, AL_Event_t * eventhdl_list, al_uint16 * events_fnd);
		#endif
	}
	//if (ret_val != AL_SUCCESS)
	//{
		//ret_val = AL_REMINDER_EVENT_NOT_PRESENT;
	//}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );
	return ret_val;

}
/************************************************************************
 ** name				: AI_PR_CheckEvtEndTime()
 **
 ** description		: 
 **
 ** input parameters	: A event end time
 **
 ** output parameters	: none
 **
 ** return type		: Boolean True  A event end time is B event start time,
 ************************************************************************/
Boolean AL_PR_CheckEvtEndTime(al_uint32 EndTime)

{
	al_uint8 count;
 
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}
	/* copy the details to internal structure */
	for( count = g_head_node; count < g_Init_Param.MaxNumOfReminders; count = g_event_details[count].next_index)
	{
		if ((g_event_details[count].details.occupied == al_true )&&(g_event_details[count].details.enable == al_true))
		{
			if (EndTime ==  g_event_details[count].details.start_local_time_secs)
			{
				return TRUE;
			}
		}
	}
	return FALSE;	

}

/************************************************************************
 ** name				: AI_PR_HandleSrvDelete()
 **
 ** description		: This API modifies the scheduled event with new information
 **
 ** input parameters	: handle - specify which service is to remove from reminder
 **
 ** output parameters	: none
 **
 ** return type		: AL_Return_t
 ************************************************************************/
AL_Return_t AI_PR_HandleSrvDelete(AL_RecHandle_t handle)
{
	if (_AI_PR_IsInit() != TRUE)
	{
		PR_ERROR("don't init\n");
		return AL_UNINITIALIZED;
	}

	al_uint8 count , prev_index;
	al_bool srv_same_ret;
	AL_Return_t ret;
	frmwrk_pfOpConext_t pf_PR_GetContext = NULL;

	AL_FW_GetContextCb(&pf_PR_GetContext);

	PR_MUTEX_LOCK(g_pr_mutex_id);

	for( count = g_head_node, prev_index = g_Init_Param.MaxNumOfReminders;
			count < g_Init_Param.MaxNumOfReminders;
			count = g_event_details[count].next_index)
	{
		if(g_event_details[count].details.occupied == al_true )
		{
			/* get the service id of the reminder*/
			srv_same_ret = (al_bool)(g_event_details[count].details.rem_details.handle == handle);
			/* check if the service id of the reminder is same as the deleted one*/
			if( al_true == srv_same_ret )
			{
				if ( g_event_details[count].details.enable == al_true )
				{
					if ( AL_SCH_UnScheduleEvent(&(g_event_details[count].sch_id)) != AL_SUCCESS)
					{
						PR_ERROR("Error to delete the schedule\n\n");
					}
				}

				/*** DELETE THE NODE ***/
				if ( prev_index == g_Init_Param.MaxNumOfReminders )
				{
					g_head_node = g_event_details[count].next_index;
					PR_DEBUG("@@@@@@@@@@ g_head_node === %d\n",g_head_node);
					prev_index = g_Init_Param.MaxNumOfReminders ;
				}
				else
				{
					g_event_details[prev_index].next_index = g_event_details[count].next_index ;
				}
                memset(&g_event_details[count].details, 0, sizeof(PR_persistent_info_t));
				g_event_details[count].details.occupied = al_false;

				/* write to persistent memory */
				if (pf_PR_GetContext != NULL)
				{
					ret = pf_PR_GetContext(FW_CONTEXT_TYPE_PR , FW_CONTEXT_OP_TYPE_WRITE,
									(al_void *)(&g_event_details[count]), (al_uint32)count);
					if (ret != AL_SUCCESS)
					{
						PR_MUTEX_UNLOCK ( g_pr_mutex_id );
						return ret;
					}
				}

			}
			else{
				prev_index = count ;
			}
		}
		else{
			prev_index = count ;
		}
	}

	PR_MUTEX_UNLOCK ( g_pr_mutex_id );
	return AL_SUCCESS;
}

al_int AL_FW_PVR_GetProgReminderId(void)
{
	return Prog_remind_id;
}

void AL_FW_PVR_SetProgReminderId(al_int id)
{
	Prog_remind_id = id;
}

/******************************************************************************
 ** $Log: ACPR_Component.c,v $
 ******************************************************************************/


