package com.github.tibolte.agendacalendarview; import com.github.tibolte.agendacalendarview.models.CalendarEvent; import com.github.tibolte.agendacalendarview.models.IDayItem; import com.github.tibolte.agendacalendarview.models.IWeekItem; import com.github.tibolte.agendacalendarview.utils.DateHelper; import android.content.Context; import android.util.Log; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Locale; /** * This class manages information about the calendar. (Events, weather info...) * Holds reference to the days list of the calendar. * As the app is using several views, we want to keep everything in one place. */ public class CalendarManager { private static final String LOG_TAG = CalendarManager.class.getSimpleName(); private static CalendarManager mInstance; private Context mContext; private Locale mLocale; private Calendar mToday = Calendar.getInstance(); private SimpleDateFormat mWeekdayFormatter; private SimpleDateFormat mMonthHalfNameFormat; /// instances of classes provided from outside private IDayItem mCleanDay; private IWeekItem mCleanWeek; /** * List of days used by the calendar */ private List<IDayItem> mDays = new ArrayList<>(); /** * List of weeks used by the calendar */ private List<IWeekItem> mWeeks = new ArrayList<>(); /** * List of events instances */ private List<CalendarEvent> mEvents = new ArrayList<>(); // region Constructors public CalendarManager(Context context) { this.mContext = context; } public static CalendarManager getInstance(Context context) { if (mInstance == null) { mInstance = new CalendarManager(context); } return mInstance; } public static CalendarManager getInstance() { return mInstance; } // endregion // region Getters/Setters public Locale getLocale() { return mLocale; } public Context getContext() { return mContext; } public Calendar getToday() { return mToday; } public void setToday(Calendar today) { this.mToday = today; } public List<IWeekItem> getWeeks() { return mWeeks; } public List<CalendarEvent> getEvents() { return mEvents; } public List<IDayItem> getDays() { return mDays; } public SimpleDateFormat getWeekdayFormatter() { return mWeekdayFormatter; } public SimpleDateFormat getMonthHalfNameFormat() { return mMonthHalfNameFormat; } // endregion // region Public methods public void buildCal(Calendar minDate, Calendar maxDate, Locale locale, IDayItem cleanDay, IWeekItem cleanWeek) { if (minDate == null || maxDate == null) { throw new IllegalArgumentException( "minDate and maxDate must be non-null."); } if (minDate.after(maxDate)) { throw new IllegalArgumentException( "minDate must be before maxDate."); } if (locale == null) { throw new IllegalArgumentException("Locale is null."); } setLocale(locale); mDays.clear(); mWeeks.clear(); mEvents.clear(); mCleanDay = cleanDay; mCleanWeek = cleanWeek; Calendar mMinCal = Calendar.getInstance(mLocale); Calendar mMaxCal = Calendar.getInstance(mLocale); Calendar mWeekCounter = Calendar.getInstance(mLocale); mMinCal.setTime(minDate.getTime()); mMaxCal.setTime(maxDate.getTime()); // maxDate is exclusive, here we bump back to the previous day, as maxDate if December 1st, 2020, // we don't include that month in our list mMaxCal.add(Calendar.MINUTE, -1); // Now iterate we iterate between mMinCal and mMaxCal so we build our list of weeks mWeekCounter.setTime(mMinCal.getTime()); int maxMonth = mMaxCal.get(Calendar.MONTH); int maxYear = mMaxCal.get(Calendar.YEAR); int currentMonth = mWeekCounter.get(Calendar.MONTH); int currentYear = mWeekCounter.get(Calendar.YEAR); // Loop through the weeks while ((currentMonth <= maxMonth // Up to, including the month. || currentYear < maxYear) // Up to the year. && currentYear < maxYear + 1) { // But not > next yr. Date date = mWeekCounter.getTime(); // Build our week list int currentWeekOfYear = mWeekCounter.get(Calendar.WEEK_OF_YEAR); IWeekItem weekItem = cleanWeek.copy(); weekItem.setWeekInYear(currentWeekOfYear); weekItem.setYear(currentYear); weekItem.setDate(date); weekItem.setMonth(currentMonth); weekItem.setLabel(mMonthHalfNameFormat.format(date)); List<IDayItem> dayItems = getDayCells(mWeekCounter); // gather days for the built week weekItem.setDayItems(dayItems); mWeeks.add(weekItem); Log.d(LOG_TAG, String.format("Adding week: %s", weekItem)); mWeekCounter.add(Calendar.WEEK_OF_YEAR, 1); currentMonth = mWeekCounter.get(Calendar.MONTH); currentYear = mWeekCounter.get(Calendar.YEAR); } } public void loadEvents(List<CalendarEvent> eventList, CalendarEvent noEvent) { for (IWeekItem weekItem : getWeeks()) { for (IDayItem dayItem : weekItem.getDayItems()) { boolean isEventForDay = false; for (CalendarEvent event : eventList) { if (DateHelper.isBetweenInclusive(dayItem.getDate(), event.getStartTime(), event.getEndTime())) { CalendarEvent copy = event.copy(); Calendar dayInstance = Calendar.getInstance(); dayInstance.setTime(dayItem.getDate()); copy.setInstanceDay(dayInstance); copy.setDayReference(dayItem); copy.setWeekReference(weekItem); // add instances in chronological order getEvents().add(copy); isEventForDay = true; } } if (!isEventForDay) { Calendar dayInstance = Calendar.getInstance(); dayInstance.setTime(dayItem.getDate()); CalendarEvent copy = noEvent.copy(); copy.setInstanceDay(dayInstance); copy.setDayReference(dayItem); copy.setWeekReference(weekItem); copy.setLocation(""); copy.setTitle(getContext().getResources().getString(R.string.agenda_event_no_events)); copy.setPlaceholder(true); getEvents().add(copy); } } } } public void loadCal (Locale locale, List<IWeekItem> lWeeks, List<IDayItem> lDays, List<CalendarEvent> lEvents) { mWeeks = lWeeks; mDays = lDays; mEvents = lEvents; setLocale(locale); } // endregion // region Private methods private List<IDayItem> getDayCells(Calendar startCal) { Calendar cal = Calendar.getInstance(mLocale); cal.setTime(startCal.getTime()); List<IDayItem> dayItems = new ArrayList<>(); int firstDayOfWeek = cal.get(Calendar.DAY_OF_WEEK); int offset = cal.getFirstDayOfWeek() - firstDayOfWeek; if (offset > 0) { offset -= 7; } cal.add(Calendar.DATE, offset); Log.d(LOG_TAG, String.format("Buiding row week starting at %s", cal.getTime())); for (int c = 0; c < 7; c++) { IDayItem dayItem = mCleanDay.copy(); dayItem.buildDayItemFromCal(cal); dayItems.add(dayItem); cal.add(Calendar.DATE, 1); } mDays.addAll(dayItems); return dayItems; } private void setLocale(Locale locale) { this.mLocale = locale; setToday(Calendar.getInstance(mLocale)); mWeekdayFormatter = new SimpleDateFormat(getContext().getString(R.string.day_name_format), mLocale); mMonthHalfNameFormat = new SimpleDateFormat(getContext().getString(R.string.month_half_name_format), locale); } // endregion }