/*
================================ COPYRIGHT ================================
The contents of this file are subject to the VTech Informations Ltd. License
of VT-OS Ver. 1.1 operating system (the "License"); you may not use this 
file except in compliance with the License.  

Software distributed under the License is distributed on an "AS IS" basis, 
WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License 
for the specific language governing rights and limitations under the License.
  
The Original Code is VT-OS Ver. 1.1 Operating System, released 
on October 1st, 1999
	
The Initial Developer of the Original Code is VTech Informations Ltd.  All 
codes are Copyright (C) VTech Informations Ltd. 1999.  All Rights Reserved.
===========================================================================
*/

/*
===========================================================================
File        :   schalarm.c
Author(s)   :   Henry Fok
Company     :   VTech Informations Ltd.
Project     :   Helio 
Date:	    :   October 1st, 1999
Purpose:	:   application c file
Revision    :   1.1
Note        :   None
===========================================================================
*/

#include "stdafx.h"
#include "app.h"
#include "appfunc.h"

//#define DEBUG_MICH
/********************************************************
* Function:	SchedulerAlarmSave
* Purpose: 	This function is called to save the set alarm settings
*		to the record 
* Scope:	application/internal
* Input:	None
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void SchedulerAlarmSave()
{
	UBYTE date[4];
	AlarmEvent evtAlarm;
	RecordID rec_id;
	USHORT row_num;
	WORD num_appmt;
	AppointmentDB *appmt_rec;
	BYTE *buffer, repeat_no[5];
	UWORD byte_read;
	UWORD rec_num;
	UWORD count;
	Err error;
	UWORD total;
	
	evtAlarm.type = 0;
	if (alarm_settings.change == FALSE)
		return;
	
	SchedulerGetDayViewDate(date);
	
	if (time_settings.alarm == TONE_ALARM || time_settings.alarm == VOICE_ALARM)
	{
		if (alarm_settings.alarm == TONE_ALARM || alarm_settings.alarm == VOICE_ALARM)
		{
		/*
		DataFindBinRecord(sch_appmt_dbid, F_DATE, 0, (BYTE*)date, 3, &rec_id);
		
		  evtAlarm.dbid = sch_appmt_dbid;
		  AlarmSetEventClass((&evtAlarm), ALARM_ONTIME);
		  evtAlarm.type = 0;
		  evtAlarm.reference = time_settings.alarm_num;
		  evtAlarm.rec_id = rec_id;
		  error = AlarmDelEvent(evtAlarm);
			*/
			AlarmDelAppEvent(SysGetActiveAppID());
		}
	}
	
	if (alarm_settings.recorded == TRUE)
	{
		if (alarm_settings.alarm != VOICE_ALARM &&
			alarm_settings.alarm != VOICE_NOT_ALARM)
		{
			DataCloseRecord(alarm_settings.dbid, alarm_settings.temp_recid);
			DataDeleteRecord(alarm_settings.dbid, alarm_settings.temp_recid, FALSE);
		}
		else
		{
			if (time_settings.alarm == VOICE_ALARM ||
				time_settings.alarm == VOICE_NOT_ALARM)
			{
				DataRecIDtoNum(sch_voice_dbid, time_settings.recid, &rec_num);
				DataOpenRecord(sch_voice_dbid, rec_num, &time_settings.recid, NULL);
				DataGetField(sch_voice_dbid, time_settings.recid, 2, &buffer, &byte_read);
				DataCloseRecord(time_settings.dbid, time_settings.recid);
				count = *((UWORD*)buffer);
				qfree(buffer);
				if (count == 1)						
				{				
					DataCloseRecord(time_settings.dbid, time_settings.recid);
					DataDeleteRecord(time_settings.dbid, time_settings.recid, FALSE);
				}
			}
			time_settings.dbid = alarm_settings.dbid;
			time_settings.recid = alarm_settings.temp_recid;
		}
	}
	else
	{
		if (time_settings.alarm == VOICE_ALARM ||
			time_settings.alarm == VOICE_NOT_ALARM)
		{
#ifdef DEBUG_MICH
			printf("\n Point 1");
			error = DataTotalRecord(sch_voice_dbid, &total);
			printf("\n error for DataTotalRecord = %ld", error);
			printf("\n total record = %ld", total);
#endif
			error = DataRecIDtoNum(sch_voice_dbid, time_settings.recid, &rec_num);
			
#ifdef DEBUG_MICH
			printf("\n Point 2");
			printf("\n error for DataRecIDtoNum = %ld", error);
			printf("\n sch_voice_dbid = %ld", sch_voice_dbid);
			printf("\n time_settings.recid = %ld", time_settings.recid);
			printf("\n rec_num = %ld", rec_num);
#endif
			
			error = DataOpenRecord(sch_voice_dbid, rec_num, &time_settings.recid, NULL);
			
#ifdef DEBUG_MICH
			printf("\n Point 3");
			printf("\n error for DataOpenRecord = %ld", error);
			printf("\n time_settings.recid = %ld", time_settings.recid);
#endif
			error = DataGetField(sch_voice_dbid, time_settings.recid, 2, &buffer, &byte_read);
			
#ifdef DEBUG_MICH
			printf("\n Point 4");
			printf("\n error for DataGetField = %ld", error);
			printf("\n buffer = %ls", buffer);
			printf("\n byte_read = %ld", byte_read);
#endif
			error = DataCloseRecord(time_settings.dbid, time_settings.recid);
			
#ifdef DEBUG_MICH
			printf("\n Point 5");
			printf("\n error for DataCloseRecord = %ld", error);
#endif
			count = *((UWORD*)buffer);
			
#ifdef DEBUG_MICH
			printf("\n Point 6");
			printf("\n count = %ld", count);
#endif
			qfree(buffer);
			
#ifdef DEBUG_MICH
			printf("\n Point 7");
#endif
			if (count == 1)						
			{
				DataCloseRecord(time_settings.dbid, time_settings.recid);
				DataDeleteRecord(time_settings.dbid, time_settings.recid, FALSE);
			}
		}
	}
	
	time_settings.alarm = alarm_settings.alarm;
	time_settings.alarm_time = alarm_settings.alarm_time;
	time_settings.alarm_num = alarm_count;
	alarm_count ++;
	
	virtual_table.vt_items[time_settings.row_num]->alarm = time_settings.alarm;
	virtual_table.vt_items[time_settings.row_num]->alarm_time = time_settings.alarm_time;
	virtual_table.vt_items[time_settings.row_num]->alarm_num = time_settings.alarm_num;
	virtual_table.vt_items[time_settings.row_num]->appmt_num = (virtual_table.vt_items[time_settings.row_num]->appmt_num)|0x80000000;
	virtual_table.vt_items[time_settings.row_num]->dbid = time_settings.dbid;
	virtual_table.vt_items[time_settings.row_num]->recid = time_settings.recid;
	/*
	if (repeat)
	{
	if (current)
	remove repeat
	else if (all)
	modify repeat
	}
	*/
	
	SchedulerGetDayViewDate(date);
	if (new_appointment == TRUE && time_settings.alarm != NO_ALARM)
		new_appointment = FALSE;
	
	SchedulerDayViewSaveAppmtData(&virtual_table, date);
	
	
	if (SchedulerCheckEarliestDayWithAlarm(date) == TRUE)
		SchedulerSetAppmtWholeDayAlarm(date);
}

/********************************************************
* Function:	SchedulerSetAppmtAlarmOn
* Purpose: 	This function is called to 
*		- set or reset an alarm of a particular appointment in one day
* Scope:	application/internal
* Input:	alarm_type		
*		alarm_time
*		date
*		hour
*		minute
*		appmt_recid
*		voice_recid
*		row_num
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void SchedulerSetAppmtAlarmOn(BYTE alarm_type, BYTE alarm_time, UWORD alarm_num, UBYTE *date,
							  BYTE hour, BYTE minute, RecordID appmt_recid,
							  RecordID voice_recid, USHORT row_num, BOOLEAN repeat_flag)
{
	AlarmEvent evtAlarm;
	SHORT year, mon, mday;
	USHORT char_count = 0;
	BYTE *appmt_msg;
	BYTE *buffer, **string;
	UWORD byte_read;
	RecordID rec_id;
	WORD num_appmt = 0, count;
	UWORD rec_num;
	Err error;
	
	evtAlarm.hit_time.msec	= 0;
	evtAlarm.hit_time.sec	= 0;
	evtAlarm.type = 0;
#ifdef DEBUG_MICH
	printf("\n ADD ALARM :Point 1");
#endif
	if (alarm_time == MIN_15_BEFORE)
		minute -= 15;
	else if (alarm_time == MIN_30_BEFORE)
		minute -= 30;
	else if (alarm_time == MIN_60_BEFORE)
		minute -= 60;
	
	if (minute < 0)
	{
		minute += 60;
		hour --;
	}
	
	if (hour < 0)
	{
		evtAlarm.hit_time.min 	= 0;
		evtAlarm.hit_time.hour	= 0;
	}
	else
	{
		evtAlarm.hit_time.hour	 = (SHORT)hour;
		evtAlarm.hit_time.min	 = (SHORT)minute;
	}
	
	year	= (SHORT)(date[0] + SYSETUP_YEAR_OFFSET);
	mon     = (SHORT)(date[1] - 1);
	mday	= (SHORT)(date[2]);
	
	evtAlarm.hit_time.mday	= mday;
	evtAlarm.hit_time.mon	= mon;
	evtAlarm.hit_time.year	= year;
	evtAlarm.hit_time.wday	= 0;
	evtAlarm.hit_time.yday	= 0;
	
	evtAlarm.app = SysGetActiveAppID();
	AlarmSetEventClass((&evtAlarm), ALARM_ONTIME);
	evtAlarm.type = 0;
	evtAlarm.reference = alarm_num;
	evtAlarm.rec_id = appmt_recid;
	
	if (repeat_flag != TRUE)
	{		
		evtAlarm.dbid = sch_appmt_dbid;
		DataFindBinRecord(sch_appmt_dbid, F_DATE, 0, (BYTE*)date, 3, &rec_id);
		DataRecIDtoNum(sch_appmt_dbid, rec_id, &rec_num);
		DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
		DataGetField(sch_appmt_dbid, rec_id, F_STRING, &buffer, &byte_read);	
		SchedulerDBGetAppmtString(buffer, byte_read, &string, &num_appmt);
		qfree(buffer);
		appmt_msg = string[row_num];
	}
	else
	{			
		evtAlarm.dbid = sch_repeat_dbid;
		DataRecIDtoNum(sch_repeat_dbid, appmt_recid, &rec_num);
		DataOpenRecord(sch_repeat_dbid, rec_num, &rec_id, NULL);
		DataGetField(sch_repeat_dbid, rec_id, F_CONTENTS, &buffer, &byte_read);
		appmt_msg = (BYTE*)qmalloc((byte_read+1) * sizeof(BYTE));
		strcpy(appmt_msg, buffer);
		qfree(buffer);
	}
	
	evtAlarm.alert_msg = (BYTE*)qmalloc(201*sizeof(BYTE));
	
	while (char_count < 200 && appmt_msg[char_count] != '\0')
	{
		evtAlarm.alert_msg[char_count] = appmt_msg[char_count];
		char_count ++;
	}
	evtAlarm.alert_msg[char_count] = '\0';
	
	if (alarm_type == VOICE_ALARM)
	{
		(evtAlarm.extra_info) = (AlarmExtraInfo *)qmalloc(sizeof(AlarmExtraInfo));
		(evtAlarm.extra_info)->type = TYPE_VOICE;
		(evtAlarm.extra_info)->dbid = sch_voice_dbid;
		(evtAlarm.extra_info)->rec_id = voice_recid;
		(evtAlarm.extra_info)->field_num = 0;
	}
	else evtAlarm.extra_info = NULL;
	
	error = AlarmDelEvent(evtAlarm);
#ifdef DEBUG_MICH
	printf("\n ADD ALARM :Point 2");
	printf("\n error for delete alarm = %ld", error);
	printf("\n evtAlarm.app = %ld", evtAlarm.app);
	printf("\n evtAlarm.type = %ld", evtAlarm.type);
	printf("\n evtAlarm.dbid = %ld", evtAlarm.dbid);
	printf("\n evtAlarm.rec_id = %ld", evtAlarm.rec_id);
	printf("\n evtAlarm.reference = %ld", evtAlarm.reference);
#endif
	AlarmAddEvent(evtAlarm);
	
	qfree(evtAlarm.alert_msg);
	if (alarm_type == VOICE_ALARM)
		qfree(evtAlarm.extra_info);
	for (count = 0; count < num_appmt; count++)
		qfree(string[count]);
	if (num_appmt != 0) qfree(string);	
#ifdef DEBUG_MICH
	printf("\n ADD ALARM :Point 2");
#endif
}

/********************************************************
* Function:	SchedulerSetAppmtWholeDayAlarm
* Purpose: 	This function is called to 
*		- set or reset alarms of appointments of a day
* Scope:	application/internal
* Input:	date				
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void SchedulerSetAppmtWholeDayAlarm(UBYTE *date)
{
	//Make sure all pointers are freed
	//Michelle 19-Jan-2001
	AlarmEvent	evtAlarm;
	USHORT		row_num = 0;
	BYTE		*buffer, **string;
	WORD		num_appmt = 0;
	UWORD		byte_read, total_rec;
	AppointmentDB	*appmt_rec;
	ArrangeRecord	*day_rec, temp_record, temp_record_1;
	RecordID	rec_id;
	UWORD		rec_num;
	Err		found;
	SHORT		count, total_record, i, j, temp;
	RepeatAttr	repeat_attr;
	AlarmAttr	*alarm_attr;
	BOOLEAN		found_record = FALSE;
	UBYTE		start_date[8], end_date[8], view_date[8];
	
	BYTE		alarm;		//Michelle 19-Jan-2001
	
#ifdef DEBUG_MICH
	printf("\n &&&&&&&&&&&&&&& SET APPMT WHOLE DAY ALARM &&&&&&&&&&&&&&&&&&");
	printf("\n set alarm date = %ld, %ld, %ld", date[0], date[1], date[2]);
#endif
	evtAlarm.type = 0;
	AlarmDelAppEvent(SysGetActiveAppID());
	found = DataFindBinRecord(sch_appmt_dbid, F_DATE, 0, (BYTE*)date, 3, &rec_id);
	if (found != TRUE)
	{
		DataTotalRecord(sch_repeat_dbid, &total_rec);
		if (total_rec == 0)
			return;
	}
	if (found == TRUE)
	{
		DataRecIDtoNum(sch_appmt_dbid, rec_id, &rec_num);
		DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
		DataGetField(sch_appmt_dbid, rec_id, F_DATA, &buffer, &byte_read);
		SchedulerDBGetAppmtRec(buffer, byte_read, &appmt_rec, &num_appmt);
		qfree(buffer);
	}
	DataTotalRecord(sch_repeat_dbid, &total_rec);
#ifdef DEBUG_MICH
	printf("\n number of appointment = %ld", num_appmt);
	printf("\n number of repeat record = %ld", total_rec);
#endif
	day_rec = (ArrangeRecord*)qmalloc((num_appmt + total_rec + 1) * sizeof(ArrangeRecord));
#ifdef DEBUG
	printf("\n address day_rec = %08x", day_rec);
#endif
	count = 0;
	if (found == TRUE)
	{
		DataRecIDtoNum(sch_appmt_dbid, rec_id, &rec_num);
		DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
		DataGetField(sch_appmt_dbid, rec_id, F_DATA, &buffer, &byte_read);
		SchedulerDBGetAppmtRec(buffer, byte_read, &appmt_rec, &num_appmt);
		qfree(buffer);
		DataGetField(sch_appmt_dbid, rec_id, F_STRING, &buffer, &byte_read);
		SchedulerDBGetAppmtString(buffer, byte_read, &string, &num_appmt);
		qfree(buffer);
		DataCloseRecord(sch_appmt_dbid, rec_id);
		
		for (row_num = 0; row_num < num_appmt; row_num++)
		{
			if (appmt_rec[row_num].alarm != NO_ALARM &&
				appmt_rec[row_num].alarm != VOICE_NOT_ALARM)
			{
				DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
				day_rec[count].record.alarm = appmt_rec[row_num].alarm;
				day_rec[count].record.alarm_num = appmt_rec[row_num].alarm_num;
				day_rec[count].record.alarm_time = appmt_rec[row_num].alarm_time;
				day_rec[count].record.appmt_num = appmt_rec[row_num].appmt_num;
				day_rec[count].record.appointment = appmt_rec[row_num].appointment;
				day_rec[count].record.dbid = appmt_rec[row_num].dbid;
				day_rec[count].record.hour = appmt_rec[row_num].hour;
				day_rec[count].record.minute = appmt_rec[row_num].minute;
				day_rec[count].record.recid = appmt_rec[row_num].recid;
				day_rec[count].appmt_recid = rec_id;
				day_rec[count].row_num = row_num;
				day_rec[count].repeat_flag = FALSE;
				count++;
				DataCloseRecord(sch_appmt_dbid, rec_id);
			}
		}
		if (num_appmt != 0) qfree(appmt_rec);
		for (row_num = 0; row_num < num_appmt; row_num++)
			qfree(string[row_num]);
		if (num_appmt != 0) qfree(string);
	}
	total_record = count;
	DataTotalRecord(sch_repeat_dbid, &total_rec);
	for(i = 0; i < total_rec; i++)
	{
		DataOpenRecord(sch_repeat_dbid, (UWORD)i, &rec_id, NULL);
		DataGetField(sch_repeat_dbid, rec_id, F_ALARM_FLAG, &buffer, &byte_read);
		alarm = *buffer;		//Michelle 19-Jan-2001
		qfree(buffer);			//Michelle 19-Jan-2001
		if (alarm == 0) continue;	//Michelle 19-Jan-2001
		else
		{
			DataGetField(sch_repeat_dbid, rec_id, F_START_TIME, &buffer, &byte_read);
			for(j = 0; j < 7; j++)
				start_date[j] = buffer[j];
			start_date[7] = 0;
			qfree(buffer);
			
			DataGetField(sch_repeat_dbid, rec_id, F_END_TIME, &buffer, &byte_read);
			for(j = 0; j < 7; j++)
				end_date[j] = buffer[j];
			end_date[7] = 0;
			qfree(buffer);			
			
			for(j = 0; j < 3; j++)
				view_date[j] = date[j];
			for(j = 3; j < 8; j++)
				view_date[j] = 0;
			
			if (IsCheckTimeBetweenStartAndEndTime(start_date, end_date, view_date) != TRUE) continue;
			//Check the repeat record whether shows on screen
			DataGetField(sch_repeat_dbid, rec_id, F_REPEAT_ATTR, &buffer, &byte_read);	//Michelle 19-Jan-2001
			repeat_attr.method = buffer[0];			//Michelle 19-Jan-2001
			qfree(buffer);					//Michelle 19-Jan-2001
			switch(repeat_attr.method)			//Michelle 19-Jan-2001
			{
			case REPEAT_DAILY:
				if (!SchedulerCheckDayViewDailyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_WEEKLY:
				if (!SchedulerCheckDayViewWeeklyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_MONTHLY_DATE:
				if (!SchedulerCheckDayViewMonthlyDateRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_MONTHLY_DAY:
				if (!SchedulerCheckDayViewMonthlyDayRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_YEARLY:
				if (!SchedulerCheckDayViewYearlyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			}
#ifdef DEBUG_MICH
			printf("\n ==== POINT 1 ==== ");
			printf("\n total record = %ld", total_record);
#endif
			temp = -1;
			for(row_num = 0; row_num < total_record; row_num++)
			{
				if (day_rec[row_num].record.hour == start_date[3] && day_rec[row_num].record.minute == start_date[4])
				{
					temp = row_num + 1;
					continue;
				}
				if (day_rec[row_num].record.hour > start_date[3] || (day_rec[row_num].record.hour == start_date[3] &&
					day_rec[row_num].record.minute > start_date[4]))
				{
					if (temp != -1)
					{
						temp_record = day_rec[temp];
						day_rec[temp].record.hour = start_date[3];
						day_rec[temp].record.minute = start_date[4];
						
						DataGetField(sch_repeat_dbid, rec_id, F_VOICE_RECID, &buffer, &byte_read);
						day_rec[temp].record.recid = *((UWORD*)buffer);
						qfree(buffer);
						
						day_rec[temp].record.dbid = sch_repeat_dbid;
						DataGetField(sch_repeat_dbid, rec_id, F_ALARM_SETTINGS, (BYTE**)&alarm_attr, &byte_read);
						day_rec[temp].record.alarm = alarm_attr->type;
						day_rec[temp].record.alarm_time = alarm_attr->time;
						day_rec[temp].record.alarm_num = alarm_attr->num;
						day_rec[temp].appmt_recid = rec_id;
						day_rec[temp].row_num = 0;
						day_rec[temp].repeat_flag = TRUE;
						qfree(alarm_attr);		//Michelle 19-Jan-2001
						count++;
						found_record = TRUE;
						break;
					}
					else
					{
						temp_record = day_rec[row_num];
						day_rec[row_num].record.hour = start_date[3];
						day_rec[row_num].record.minute = start_date[4];
						
						DataGetField(sch_repeat_dbid, rec_id, F_VOICE_RECID, &buffer, &byte_read);
						//Bug fixd 19-Jan-2001
						day_rec[row_num].record.recid = *((UWORD*)buffer);	//Michelle 19-Jan-2001
						qfree(buffer);
						
						day_rec[row_num].record.dbid = sch_repeat_dbid;
						DataGetField(sch_repeat_dbid, rec_id, F_ALARM_SETTINGS, (BYTE**)&alarm_attr, &byte_read);
						day_rec[row_num].record.alarm = alarm_attr->type;
						day_rec[row_num].record.alarm_time = alarm_attr->time;
						day_rec[row_num].record.alarm_num = alarm_attr->num;
						day_rec[row_num].appmt_recid = rec_id;
						day_rec[row_num].row_num = 0;
						day_rec[row_num].repeat_flag = TRUE;
						qfree(alarm_attr);		//Michelle 19-Jan-2001
						temp = row_num;
						count++;
						found_record = TRUE;
						break;
					}
				}
			}
#ifdef DEBUG_MICH
			printf("\n ==== POINT 2 ==== ");
			printf("\n total record = %ld", count);
#endif
			if (found_record == TRUE)
			{
				for(row_num = 0; row_num < count; row_num++)
				{
					if (row_num > (temp))
					{
						temp_record_1 = day_rec[row_num];
						day_rec[row_num] = temp_record;
						temp_record = temp_record_1;
					}
				}
				found_record = FALSE;
				day_rec[count] = temp_record;
			}
			else
			{
				day_rec[count].record.hour = start_date[3];
				day_rec[count].record.minute = start_date[4];
				
				DataGetField(sch_repeat_dbid, rec_id, F_VOICE_RECID, &buffer, &byte_read);
				day_rec[count].record.recid = *((UWORD*)buffer);
				qfree(buffer);
				
				day_rec[count].record.dbid = 0;
				day_rec[count].record.appmt_num = 0;
				DataGetField(sch_repeat_dbid, rec_id, F_ALARM_SETTINGS, (BYTE**)&alarm_attr, &byte_read);
				day_rec[count].record.alarm = alarm_attr->type;
				day_rec[count].record.alarm_time = alarm_attr->time;
				day_rec[count].record.alarm_num = alarm_attr->num;
				day_rec[count].appmt_recid = rec_id;
				day_rec[count].row_num = 0;
				day_rec[count].repeat_flag = TRUE;
				qfree(alarm_attr);		//Michelle 19-Jan-2001
				count++;
				total_record++;
			}
			total_record = count;
		}
		DataCloseRecord(sch_repeat_dbid, rec_id);
	}
	for(i = 0; i < total_record; i++)
	{
#ifdef DEBUG_MICH
		printf("\n day_rec[%d].record.alarm = %ld", i, day_rec[i].record.alarm);
		printf("\n day_rec[%d].record.alarm_time = %ld", i, day_rec[i].record.alarm_time);
		printf("\n day_rec[%d].record.alarm_num = %ld", i, day_rec[i].record.alarm_num);
		printf("\n day_rec[%d].record.hour = %ld", i, day_rec[i].record.hour);
		printf("\n day_rec[%d].record.minute = %ld", i, day_rec[i].record.minute);
		printf("\n day_rec[%d].appmt_recid = %ld", i, day_rec[i].appmt_recid);
		printf("\n day_rec[%d].record.recid = %ld", i, day_rec[i].record.recid);
		printf("\n day_rec[%d].row_num = %ld", i, day_rec[i].row_num);
#endif
		if (!day_rec[i].repeat_flag)
			SchedulerSetAppmtAlarmOn(day_rec[i].record.alarm, day_rec[i].record.alarm_time, 
			day_rec[i].record.alarm_num, date, day_rec[i].record.hour,
			day_rec[i].record.minute, day_rec[i].appmt_recid,
			day_rec[i].record.recid, day_rec[i].row_num, FALSE);
		else SchedulerSetAppmtAlarmOn(day_rec[i].record.alarm, day_rec[i].record.alarm_time, 
			day_rec[i].record.alarm_num, date, day_rec[i].record.hour,
			day_rec[i].record.minute, day_rec[i].appmt_recid,
			day_rec[i].record.recid, day_rec[i].row_num, TRUE);
		
	}
	if (day_rec != NULL) qfree(day_rec);
}

/********************************************************
* Function:	SchedulerCheckWholeDayAlarmOff
* Purpose: 	this function is to check whether the date of the 
*		input record id has alarm or not
* Scope:	application/internal
* Input:	rec_id
* Output:	None
* Return:	TRUE		no alarm
*		FALSE		there is at least one alarm
* Comment: 	None
*********************************************************/
BOOLEAN SchedulerCheckWholeDayAlarmOff(RecordID rec_id)
{
	BYTE *buffer;
	UWORD byte_read;
	UWORD rec_num;
	
	DataRecIDtoNum(sch_appmt_dbid, rec_id, &rec_num);
	DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
	DataGetField(sch_appmt_dbid, rec_id, F_ALARM, &buffer, &byte_read);
	DataCloseRecord(sch_appmt_dbid, rec_id);
	if (*buffer == 1)
		return FALSE;
	else return TRUE;
}

/********************************************************
* Function:	SchedulerSetAppmtAlarmOff
* Purpose: 	This function is called to set an appointment 
*		alarm off
* Scope:	application/internal
* Input:	current_rec_id
*		row_num
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void SchedulerSetAppmtAlarmOff(RecordID current_rec_id, USHORT row_num)
{
	BYTE *buffer;
	UWORD byte_read;
	AppointmentDB *appmt_rec;
	WORD num_appmt;
	WORD count;
	BYTE alarm;
	RecordID rec_id;
	BYTE **string;
	BYTE *appmt_rec_buf, *appmt_string_buf;
	WORD num_bytes_appmt, num_bytes_string;
	UWORD rec_num;
	
	DataRecIDtoNum(sch_appmt_dbid, current_rec_id, &rec_num);
	DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
	DataGetField(sch_appmt_dbid, current_rec_id, F_DATA, &buffer, &byte_read);
	SchedulerDBGetAppmtRec(buffer, byte_read, &appmt_rec, &num_appmt);
	qfree(buffer);
	DataGetField(sch_appmt_dbid, current_rec_id, F_STRING, &buffer, &byte_read);
	SchedulerDBGetAppmtString(buffer, byte_read, &string, &num_appmt);
	qfree(buffer);
	
	if (appmt_rec[row_num].alarm == VOICE_ALARM)
        appmt_rec[row_num].alarm = VOICE_NOT_ALARM;
	else appmt_rec[row_num].alarm = NO_ALARM;
	appmt_rec[row_num].alarm_time	= EXACT_TIME;
	appmt_rec[row_num].alarm_num	= 0;
	
	SchedulerDBAppmtToBuffer(appmt_rec, string, num_appmt, 
		&appmt_rec_buf, &appmt_string_buf, &num_bytes_appmt,
		&num_bytes_string);
	DataWriteField(sch_appmt_dbid, current_rec_id, F_DATA, num_bytes_appmt, appmt_rec_buf);
	DataWriteField(sch_appmt_dbid, current_rec_id, F_STRING, num_bytes_string, appmt_string_buf);
	qfree(appmt_rec_buf);
	qfree(appmt_string_buf);
	qfree(appmt_rec);
	for (count = 0; count < num_appmt; count++)
		qfree(string[count]);
	qfree(string[count]);
	
	for (count = 0; count < num_appmt; count++)
	{
		if (appmt_rec[count].alarm != NO_ALARM &&
			appmt_rec[count].alarm != VOICE_NOT_ALARM)
		{
			alarm = 1;
			DataWriteField(sch_appmt_dbid, current_rec_id, F_ALARM, 1, (BYTE*)&alarm);
			return ;
		}
	}
	alarm = 0;
	DataWriteField(sch_appmt_dbid, current_rec_id, F_ALARM, 1, (BYTE*)&alarm);
	DataCloseRecord(sch_appmt_dbid, current_rec_id);
}

/********************************************************
* Function:	SchedulerGetNextRecWithAlarm
* Purpose: 	This fucntion is called to get next record id 
*		that has alarm 
* Scope:	application/internal
* Input:	current_rec_id				
* Output:	next_rec_id
* Return:	TRUE		found
*		FALSE		not found
* Comment: 	None
*********************************************************/
BOOLEAN SchedulerGetNextRecWithAlarm(RecordID current_rec_id, RecordID *next_rec_id)
{
	UWORD current_rec_num;
	UWORD rec_num;
	UWORD total_rec;
	BYTE *buffer;
	UWORD byte_read;
	
	DataRecIDtoNum(sch_appmt_dbid, current_rec_id, &current_rec_num);
	DataTotalRecord(sch_appmt_dbid, &total_rec);
	
	for (rec_num = current_rec_num + 1; rec_num < total_rec; rec_num++)
	{
		DataOpenRecord(sch_appmt_dbid, rec_num, next_rec_id, NULL);
		DataGetField(sch_appmt_dbid, *next_rec_id, F_ALARM, &buffer, &byte_read);
		if (*buffer == 1)
		{
			qfree(buffer);
			DataCloseRecord(sch_appmt_dbid, *next_rec_id);
			return TRUE;
		}
		qfree(buffer);
		DataCloseRecord(sch_appmt_dbid, *next_rec_id);
	}
	return FALSE;
}

/********************************************************
* Function:	SchedulerCheckEarliestDayWithAlarm
* Purpose: 	This function is called to check whether the input date is 
*		the earliest date with alarm or not
* Scope:	application/internal
* Input:	date				
* Output:	None
* Return:	TRUE		
*		FALSE		
* Comment: 	None
*********************************************************/
BOOLEAN SchedulerCheckEarliestDayWithAlarm(UBYTE *date)
{
	UWORD 		input_rec_num, total_rec;
	RecordID 	input_rec_id, rec_id;
	RTM 		time, temp_time, temp_time1;
	UBYTE 		cur_date[3], alarm_date[3], start_date[8], end_date[8], view_date[8];
	AppointmentDB	*appmt_rec;
	BOOLEAN 	result;
	BYTE		alarm, *buffer, alarm_flag, alarm_time;
	UWORD 		byte_read;
	WORD		num_appmt, count;
	SHORT		hour, minute, i, j;
	AlarmAttr	*alarm_attr;
	Err		found;
	RepeatAttr	*repeat_attr;
	
#ifdef DEBUG
	printf("\n ^^^^^^^^^ CHECK EARLIEST DAY WITH ALARM ^^^^^^^^^^^^^^^^");
	printf("\n view year, view mon, view date = %ld, %ld, %ld", date[0], date[1], date[2]);
#endif
	found = DataFindBinRecord(sch_appmt_dbid, F_DATE, 0, (BYTE*)date, 3, &input_rec_id);
	if (found != TRUE)
	{
		DataTotalRecord(sch_repeat_dbid, &total_rec);
		if (total_rec == 0)
			return FALSE;
	}
	temp_time1.msec = 0;
	temp_time1.sec = 0;
	temp_time1.min = 0;
	temp_time1.hour = 0;
	temp_time1.mday = 0;
	temp_time1.mon = 0;
	temp_time1.year = 0;
	temp_time1.wday = 0;
	temp_time1.yday = 0;
	
	RtcGetTime(&time);
	cur_date[0] = (BYTE)(time.year - SYSETUP_YEAR_OFFSET);
	cur_date[1] = (BYTE)(time.mon + 1);
	cur_date[2] = (BYTE)(time.mday);
	
	result = AlarmGetLastAlarmTime(SysGetActiveAppID(), &time);
	
	alarm_date[0] = (BYTE)(time.year - SYSETUP_YEAR_OFFSET);
	alarm_date[1] = (BYTE)(time.mon + 1);
	alarm_date[2] = (BYTE)(time.mday);
	
	if (found == TRUE)
	{
		DataRecIDtoNum(sch_appmt_dbid, input_rec_id, &input_rec_num);
		DataOpenRecord(sch_appmt_dbid, input_rec_num, &input_rec_id, NULL);
		DataGetField(sch_appmt_dbid, input_rec_id, F_ALARM, &buffer, &byte_read);
		if (*buffer == 0)
		{
			qfree(buffer);
			DataCloseRecord(sch_appmt_dbid, input_rec_id);
			return FALSE;
		}
		else if ((result == TRUE && SchedulerCompareDate(date, alarm_date) >= 1 && SchedulerCompareDate(date, cur_date) <= 1) || (result == FALSE))
		{
			qfree(buffer);
			DataGetField(sch_appmt_dbid, input_rec_id, F_DATA, &buffer, &byte_read);
			SchedulerDBGetAppmtRec(buffer, byte_read, &appmt_rec, &num_appmt);
			qfree(buffer);
			alarm = 0;
			for (count = 0; count < num_appmt; count++)
			{
				if (appmt_rec[count].alarm == NO_ALARM || appmt_rec[count].alarm == VOICE_NOT_ALARM)
					continue;
				temp_time = temp_time1;
				temp_time.year = (SHORT)(date[0] + SYSETUP_YEAR_OFFSET);
				temp_time.mon  = (SHORT)(date[1] - 1);
				temp_time.mday = (SHORT)(date[2]);
				
				temp_time.hour = (SHORT)(appmt_rec[count].hour);
				temp_time.min = (SHORT)(appmt_rec[count].minute);
				
				if (appmt_rec[count].alarm_time == MIN_15_BEFORE)
					temp_time.min -= 15;
				else if (appmt_rec[count].alarm_time == MIN_30_BEFORE)
					temp_time.min -= 30;
				else if (appmt_rec[count].alarm_time == MIN_60_BEFORE)
					temp_time.min -= 60;
				
				if (temp_time.min < 0)
				{
					temp_time.min += 60;
					temp_time.hour --;
				}
				
				if (temp_time.hour < 0)
				{
					temp_time.hour = 0;
					temp_time.min = 0;
				}
				RtcGetTime(&time);
				//kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
				if (RtcCompareTime(&temp_time, &time) == TRUE)
				{
					//				if (Dt_CmpDate(&temp_time, &time) > 0)
					//				{
					//kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
					alarm = 1;
#ifdef DEBUG
					printf("\n appointment record with alarm set is found");
#endif
					break;
				}
			}
			qfree(appmt_rec);
			DataCloseRecord(sch_appmt_dbid, input_rec_id);
			if (alarm == 1)
				return TRUE;
		}
	}
	// Check alarm from repeat records
	DataTotalRecord(sch_repeat_dbid, &total_rec);
	for(i = 0; i < total_rec; i++)
	{
		alarm = 0;
		DataOpenRecord(sch_repeat_dbid, (UWORD)i, &rec_id, NULL);
		DataGetField(sch_repeat_dbid, rec_id, F_ALARM_FLAG, &buffer, &byte_read);
		if (*buffer == 0)
		{
			qfree(buffer);
			DataCloseRecord(sch_repeat_dbid, rec_id);
			continue;
		}
		else if ((result == TRUE && SchedulerCompareDate(date, alarm_date) >= 1 && SchedulerCompareDate(date, cur_date) <= 1) || (result == FALSE))
		{
			qfree(buffer);
			DataGetField(sch_repeat_dbid, rec_id, F_START_TIME, &buffer, &byte_read);
			for(j = 0; j < 7; j++)
				start_date[j] = buffer[j];
			start_date[7] = 0;
			qfree(buffer);
			DataGetField(sch_repeat_dbid, rec_id, F_END_TIME, &buffer, &byte_read);
			for(j = 0; j < 7; j++)
				end_date[j] = buffer[j];
			end_date[7] = 0;
			qfree(buffer);
			for(j = 0; j < 3; j++)
				view_date[j] = date[j];
			for(j = 3; j < 8; j++)
				view_date[j] = 0;
			
			if (IsCheckTimeBetweenStartAndEndTime(start_date, end_date, view_date) != TRUE) continue;
			//Checking the repeat record whether shows on screen
			DataGetField(sch_repeat_dbid, rec_id, F_REPEAT_ATTR, (BYTE**)&repeat_attr, &byte_read);
			switch(repeat_attr->method)
			{
			case REPEAT_DAILY:
				qfree(repeat_attr);
				if (!SchedulerCheckDayViewDailyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_WEEKLY:
				qfree(repeat_attr);
				if (!SchedulerCheckDayViewWeeklyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_MONTHLY_DATE:
				qfree(repeat_attr);
				if (!SchedulerCheckDayViewMonthlyDateRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_MONTHLY_DAY:
				qfree(repeat_attr);
				if (!SchedulerCheckDayViewMonthlyDayRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			case REPEAT_YEARLY:
				qfree(repeat_attr);
				if (!SchedulerCheckDayViewYearlyRepeat(rec_id, view_date, start_date, end_date, NULL, OTHER))
					continue;
				else break;
			}
			temp_time.year = (SHORT)(date[0] + SYSETUP_YEAR_OFFSET);
			temp_time.mon = (SHORT)(date[1] - 1);
			temp_time.mday = (SHORT)date[2];
			temp_time.hour = (SHORT)start_date[3];
			temp_time.min = (SHORT)start_date[4];
			DataGetField(sch_repeat_dbid, rec_id, F_ALARM_SETTINGS, (BYTE**)&alarm_attr, &byte_read);
			alarm_time = alarm_attr->time;
			qfree(alarm_attr);
			if (alarm_time == MIN_15_BEFORE)
				temp_time.min -= 15;
			else if (alarm_time == MIN_30_BEFORE)
				temp_time.min -= 30;
			else if (alarm_time == MIN_60_BEFORE)
				temp_time.min -= 60;
			
			if (temp_time.min < 0)
			{
				temp_time.min += 60;
				temp_time.hour--;
			}
			if (temp_time.hour < 0)
			{
				temp_time.min = 0;
				temp_time.hour = 0;
			}
			RtcGetTime(&time);
			//kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
			if (RtcCompareTime(&temp_time, &time) == TRUE)
			{
				//			if (Dt_CmpDate(&temp_time, &time) > 0)
				//			{
				//kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
				alarm = 1;
#ifdef DEBUG
				printf("\n repeat record with alarm set is found");
#endif
				DataCloseRecord(sch_repeat_dbid, rec_id);
				break;
			}
		}
		DataCloseRecord(sch_repeat_dbid, rec_id);
	}
	if (alarm == 1)
		return TRUE;
	else return FALSE;
}

/********************************************************
* Function:	SchedulerCompareDate
* Purpose: 	This function is called to compare two input date
* Scope:	application/internal
* Input:	input_date_0
*		input_date_1
* Output:	None
* Return:	0			input_date_0 < input_date_1
*		1			input_date_0 = input_date_1
*		2			input_date_0 > input_date_1
* Comment: 	None
*********************************************************/
BYTE SchedulerCompareDate(UBYTE *input_date_0, UBYTE *input_date_1)
{
	USHORT count; 
	
	for (count = 0; count < 3; count++)
	{
		if (input_date_0[count] > input_date_1[count])
			return 0;
		else if (input_date_0[count] < input_date_1[count])
			return 2;
	}
	return 1;
}

/********************************************************
* Function:	SchedulerSaveAndSetAlarm
* Purpose:
* Scope:	application/internal
* Input:	None
* Output:	None
* Return:	None
* Comment: 	None
*********************************************************/
void SchedulerSaveAndSetAlarm()
{
	UBYTE    date[4];
	
	SchedulerGetDayViewDate(date);
	SchedulerDayViewSaveAppmtData(&virtual_table, date);
	if (SchedulerCheckEarliestDayWithAlarm(date) == TRUE)
		SchedulerSetAppmtWholeDayAlarm(date);
}

BOOLEAN SchedulerFindNextAppmtAlarmDate(UBYTE *view_date, UBYTE *appmt_alarm_date)
{
	UWORD		total;
	RecordID	rec_id;
	BOOLEAN		found;
	UWORD		rec_num, byte_read;
	BYTE		*buffer;
	
	DataTotalRecord(sch_appmt_dbid, &total);
	if (total == 0)
		return FALSE;
	found = DataFindBinRecord(sch_appmt_dbid, F_DATE, 0, (BYTE*)view_date, 3, &rec_id);
	if (!found)
	{
		rec_num = 0;
		do
		{
			DataOpenRecord(sch_appmt_dbid, rec_num, &rec_id, NULL);
			DataGetField(sch_appmt_dbid, rec_id, F_ALARM, &buffer, &byte_read);
			if (*buffer == 0)
			{
				qfree(buffer);
				DataCloseRecord(sch_appmt_dbid, rec_id);
				rec_num++;
				continue;
			}
			else
			{
				DataGetField(sch_appmt_dbid, rec_id, F_DATE, &buffer, &byte_read);
				if (SchedulerCompareDate(buffer, view_date) <= 1)
				{
					appmt_alarm_date[0] = buffer[0];
					appmt_alarm_date[1] = buffer[1];
					appmt_alarm_date[2] = buffer[2];
					appmt_alarm_date[3] = 0;
					return TRUE;
				}
				rec_num++;
			}
		}while(rec_num >= total);
	}
	return FALSE;
}
