BOOL CXTPCalendarRemindersManager::_GetMaxExceptionReminder(
									CXTPCalendarRecurrencePattern* pPattern,
									int& rnMinutes)
{
	ASSERT(pPattern);
	if (!pPattern)
	{
		return FALSE;
	}

	CXTPCalendarEventsPtr ptrExcAr = pPattern->GetExceptions();
	if (!ptrExcAr)
	{
		return FALSE;
	}

	BOOL bExists = FALSE;
	rnMinutes = 0;

	int nCount = ptrExcAr->GetCount();
	for (int i = 0; i < nCount; i++)
	{
		CXTPCalendarEvent* pExc = ptrExcAr->GetAt(i, FALSE);
		if (pExc && pExc->IsReminder())
		{
			rnMinutes = max(rnMinutes, pExc->GetReminderMinutesBeforeStart());
			bExists = TRUE;
		}
	}
	return bExists;
}
BOOL CXTPCalendarRemindersManager::UpdateDataFromDP(COleDateTime dtFrom,
													COleDateTimeSpan spPeriod)
{
	ASSERT(m_pResourcesNf);
	if (!m_pResourcesNf || 0 == m_pResourcesNf->GetCount())
	{
		m_dtLastUpdateTime = (DATE)0;
		return FALSE;
	}

	DWORD dwTime0 = ::GetTickCount();
	DBG_REMINDERS_TRACE(_T("%s - CXTPCalendarRemindersManager::start retrieve UpcomingEvents().  \n"),
						CXTPCalendarUtils::GetCurrentTime().Format());

	CWaitCursor _WC;

	int nWaitingCount = m_arWaitingReminders.GetCount();
	int nActiveCount = m_arActiveReminders.GetCount();
	// ???
	m_arWaitingReminders.RemoveAll();
	m_arActiveReminders.RemoveAll();

	CXTPCalendarEventsPtr ptrEvents;
	BOOL bDataAvailable = GetUpcomingEventsAll(dtFrom, spPeriod, ptrEvents);

	if (bDataAvailable)
	{
		int nCount = ptrEvents ? ptrEvents->GetCount() : 0;
		for (int i = 0; i < nCount; i++)
		{
			CXTPCalendarEvent* pEvent = ptrEvents->GetAt(i, FALSE);
			ASSERT(pEvent);

			ProcessNewEvent(pEvent, dtFrom, spPeriod);
		}
		m_arActiveReminders.Sort();

		m_dtLastUpdateTime = dtFrom;

		int nWaitingCount2 = m_arWaitingReminders.GetCount();

		//------------------------------------
		DWORD dwTime1 = ::GetTickCount();
		DBG_REMINDERS_TRACE(_T("%s - CXTPCalendarRemindersManager::STOP retrieve UpcomingEvents(). time=%d ms, count = %d \n"),
			CXTPCalendarUtils::GetCurrentTime().Format(), (dwTime1 - dwTime0), nWaitingCount2);

		//------------------------------------------------------------
		return (nWaitingCount != 0 || nWaitingCount2 != 0 || nActiveCount != 0);
	}

	//===================================================
	DBG_REMINDERS_TRACE(_T("%s - CXTPCalendarRemindersManager::SKIP  retrieve UpcomingEvents(). *** Some Data Closed. *** \n"),
						CXTPCalendarUtils::GetCurrentTime().Format());

	m_dtLastUpdateTime = (DATE)0;
	return FALSE;
}
BOOL CXTPCalendarRemindersManager::GetUpcomingEventsAll(COleDateTime dtFrom,
							COleDateTimeSpan spPeriod, CXTPCalendarEventsPtr& rptrEvents)
{
	rptrEvents = NULL;

	if (!m_pResourcesNf || !m_pResourcesNf->GetResourcesGroupedByDP())
	{
		ASSERT(FALSE);
		return FALSE;
	}

	CXTPCalendarResources* pRCgroups = m_pResourcesNf->GetResourcesGroupedByDP();

	int i;
	int nCount = pRCgroups->GetCount();

	//-- check is all data providers opened -------------
	for (i = 0; i < nCount; i++)
	{
		CXTPCalendarResource* pRC = pRCgroups->GetAt(i);
		ASSERT(pRC);
		CXTPCalendarData* pData = pRC ? pRC->GetDataProvider() : NULL;
		ASSERT(pData);

		if (!pData || !pData->IsOpen())
		{
			return FALSE;
		}
	}

	//-- read data ----------------
	for (i = 0; i < nCount; i++)
	{
		CXTPCalendarResource* pRC = pRCgroups->GetAt(i);
		ASSERT(pRC);
		CXTPCalendarData* pData = pRC ? pRC->GetDataProvider() : NULL;

		if (!pData || !pData->IsOpen())
		{
			ASSERT(FALSE);
			continue;
		}

		CXTPCalendarEventsPtr ptrEv = pData->GetUpcomingEvents(dtFrom, spPeriod);

		if (rptrEvents)
		{
			rptrEvents->Append(ptrEv);
		}
		else
		{
			rptrEvents = ptrEv;
		}

		pRC->FilterEventsByScheduleID(rptrEvents);
	}
	return TRUE;
}
BOOL CXTPCalendarController::_HasEvents(COleDateTime dtDay)
{
    ASSERT(m_pResourcesNf);
    if (!m_pResourcesNf)
    {
        return FALSE;
    }

    const CXTPCalendarResources* pRCx = m_pResourcesNf->GetResourcesGroupedByDP();
    int nRCCount = pRCx ? pRCx->GetCount() : 0;

    for (int i = 0; i < nRCCount; i++)
    {
        CXTPCalendarResource* pRC = pRCx->GetAt(i);
        ASSERT(pRC);
        CXTPCalendarEventsPtr ptrEvents = pRC ? pRC->RetrieveDayEvents(dtDay) : NULL;
        if (ptrEvents && ptrEvents->GetCount() > 0)
        {
            return TRUE;
        }
    }

    return FALSE;
}
void CXTPCalendarEventRecurrenceDlg::OnOK()
{
	int nMin = GetChangedComboTimeInMin(m_wndCbStart);
	if (nMin == -1)
	{
		MsgBox_WrongValue(&m_wndCbStart);
		return;
	}

	nMin = GetChangedComboTimeInMin(m_wndCbEnd);
	if (nMin == -1)
	{
		MsgBox_WrongValue(&m_wndCbEnd);
		return;
	}

	int nDuration_min = GetDurationComboInMin();
	if (nDuration_min < 0)
	{
		MsgBox_WrongValue(&m_wndCbDuration);
		return;
	}

	UpdateData();

	CXTPCalendarEventsPtr ptrExceptions = m_ptrPattern->GetExceptions();
	if (ptrExceptions && ptrExceptions->GetCount())
	{
		// Any exceptions associated with this recurring appointment will be lost. If any of the exceptions are meetings, the attendees will not be notified. Is this OK?
		int nRes = XTPResourceManager()->ShowMessageBox(XTP_IDS_CALENDAR_REMOVE_EXCEPTIONS, MB_OKCANCEL);
		if (nRes != IDOK)
		{
			return;
		}
		m_ptrPattern->RemoveAllExceptions();
	}

	m_dtStart = CXTPCalendarUtils::ResetDate(m_dtStart);
	m_ptrPattern->SetStartTime(m_dtStart);

	m_ptrPattern->SetDurationMinutes(nDuration_min);

	//----------------------------------------------------------
	XTP_CALENDAR_RECURRENCE_OPTIONS opt;

	int nRadio = GetCheckedRadioButton(XTP_IDC_RADIO_DAILY, XTP_IDC_RADIO_YEARLY);
	switch (nRadio)
	{
	case XTP_IDC_RADIO_DAILY:
		{
			if (m_nDayInterval < 1 || m_nDayInterval > 999)
			{
				MsgBox_WrongValueRange(XTP_IDC_EDIT_DAYINTERVAL, 1, 999);
				return;
			}

			opt.m_nRecurrenceType = xtpCalendarRecurrenceDaily;
			opt.m_Daily.bEveryWeekDayOnly = GetCheckedRadioButton(XTP_IDC_RADIO_EVERYDAY, XTP_IDC_RADIO_EVERYWORKDAY) == XTP_IDC_RADIO_EVERYWORKDAY;

			if (opt.m_Daily.bEveryWeekDayOnly)
			{
				opt.m_Daily.nIntervalDays = 1;
				if (nWorkWeekMask != xtpCalendarDayMo_Fr)
				{
					opt.m_nRecurrenceType = xtpCalendarRecurrenceWeekly;
					opt.m_Weekly.nIntervalWeeks = 1;
					opt.m_Weekly.nDayOfWeekMask = 0;
					if (nWorkWeekMask & xtpCalendarDayMonday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayMonday;
					if (nWorkWeekMask & xtpCalendarDayTuesday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayTuesday;
					if (nWorkWeekMask & xtpCalendarDayWednesday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayWednesday;
					if (nWorkWeekMask & xtpCalendarDayThursday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayThursday;
					if (nWorkWeekMask & xtpCalendarDayFriday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayFriday;
					if (nWorkWeekMask & xtpCalendarDaySaturday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDaySaturday;
					if (nWorkWeekMask & xtpCalendarDaySunday)
						opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDaySunday;
				}
			}
			else
				opt.m_Daily.nIntervalDays = m_nDayInterval;
			break;

		}
	case XTP_IDC_RADIO_WEEKLY:

		if (m_nWeeklyInterval < 1 || m_nWeeklyInterval > 999)
		{
			MsgBox_WrongValueRange(XTP_IDC_EDIT_WEEKLY_INTERVAL, 1, 999);
			return;
		}

		opt.m_nRecurrenceType = xtpCalendarRecurrenceWeekly;
		opt.m_Weekly.nIntervalWeeks = m_nWeeklyInterval;
		opt.m_Weekly.nDayOfWeekMask = 0;
		if (m_bMonday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayMonday;
		if (m_bTuesday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayTuesday;
		if (m_bWednesday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayWednesday;
		if (m_bThursday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayThursday;
		if (m_bFriday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDayFriday;
		if (m_bSaturday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDaySaturday;
		if (m_bSunday)
			opt.m_Weekly.nDayOfWeekMask |= xtpCalendarDaySunday;

		break;
	case XTP_IDC_RADIO_MONTHLY:
		if (GetCheckedRadioButton(XTP_IDC_RADIO_MONTH_RECUR, XTP_IDC_RADIO_MONTH_IN) ==
			XTP_IDC_RADIO_MONTH_RECUR)
		{
			if (m_nMonthInterval < 1 || m_nMonthInterval > 999)
			{
				MsgBox_WrongValueRange(XTP_IDC_EDIT_MONTH_MONTH, 1, 999);
				return;
			}
			if (m_MonthDate < 1 || m_MonthDate > 31)
			{
				MsgBox_WrongValueRange(XTP_IDC_EDIT_MONTH_DATE, 1, 31);
				return;
			}

			opt.m_nRecurrenceType = xtpCalendarRecurrenceMonthly;
			opt.m_Monthly.nIntervalMonths = m_nMonthInterval;
			opt.m_Monthly.nDayOfMonth = m_MonthDate;
		}
		else
		{
			if (m_nMonthInterval2 < 1 || m_nMonthInterval2 > 999)
			{
				MsgBox_WrongValueRange(XTP_IDC_EDIT_MONTH_MONTH2, 1, 999);
				return;
			}

			opt.m_MonthNth.nIntervalMonths = m_nMonthInterval2;
			opt.m_nRecurrenceType = xtpCalendarRecurrenceMonthNth;
			opt.m_MonthNth.nWhichDayMask = (int)m_wndCbMonthDay.GetItemData(m_wndCbMonthDay.GetCurSel());

			opt.m_MonthNth.nWhichDay = (int)m_wndCbMonthWhich.GetItemData(m_wndCbMonthWhich.GetCurSel());
		}

		break;
	case XTP_IDC_RADIO_YEARLY:
		opt.m_nRecurrenceType = xtpCalendarRecurrenceYearly;
		if (GetCheckedRadioButton(XTP_IDC_RADIO_YEAR_RECUR, XTP_IDC_RADIO_YEAR_IN) ==
			XTP_IDC_RADIO_YEAR_RECUR)
		{
			if (m_nDayOfMonth < 1 || m_nDayOfMonth > 31)
			{
				MsgBox_WrongValueRange(XTP_IDC_EDIT_YEAR_DATE, 1, 31);
				return;
			}

			opt.m_Yearly.nDayOfMonth = m_nDayOfMonth;
			opt.m_Yearly.nMonthOfYear = (int)m_wndYearMonth.GetItemData(m_wndYearMonth.GetCurSel());
		}
		else
		{
			opt.m_nRecurrenceType = xtpCalendarRecurrenceYearNth;

			opt.m_YearNth.nMonthOfYear = (int)m_wndComboYearMonth2.GetItemData(m_wndComboYearMonth2.GetCurSel());

			opt.m_YearNth.nWhichDay = (int)m_wndCbYearWhich.GetItemData(m_wndCbYearWhich.GetCurSel());

			opt.m_YearNth.nWhichDayMask = (int)m_wndCbYearDay.GetItemData(m_wndCbYearDay.GetCurSel());
		}

		break;
	}

	m_ptrPattern->SetRecurrenceOptions(opt);

	//-----------------------------------------------------------------------
	m_dtStartDate = CXTPCalendarUtils::ResetTime(m_dtStartDate);
	m_ptrPattern->SetPatternStartDate(m_dtStartDate);

	nRadio = GetCheckedRadioButton(XTP_IDC_RADIO_NOEND, XTP_IDC_RADIO_ENDBY);
	switch (nRadio)
	{
	case XTP_IDC_RADIO_ENDBY:
		if (m_dtEndDate < m_dtStartDate)
		{
			MsgBox_WrongValue(GetDlgItem(XTP_IDC_DATETIMEPICKER_ENDDATE));
			return;
		}
		m_ptrPattern->SetPatternEndDate(m_dtEndDate);
		break;

	case XTP_IDC_RADIO_ENDAFTER:
		if (m_nOccurNum < 1 || m_nOccurNum > 999)
		{
			MsgBox_WrongValueRange(XTP_IDC_EDIT_OCCUR, 1, 999);
			return;
		}
		m_ptrPattern->SetEndAfterOccurrences(m_nOccurNum);
		break;
	case XTP_IDC_RADIO_NOEND:
		m_ptrPattern->SetNoEndDate();
		break;
	}

	//-----------------------------------------------------------------------
	VERIFY(m_ptrMasterEvent->UpdateRecurrence(m_ptrPattern));

	CDialog::OnOK();
}