package fr.paug.androidmakers.ui.fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import java.lang.ref.WeakReference;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import fr.paug.androidmakers.R;
import fr.paug.androidmakers.manager.AgendaRepository;
import fr.paug.androidmakers.model.Room;
import fr.paug.androidmakers.model.ScheduleSlot;
import fr.paug.androidmakers.model.Session;
import fr.paug.androidmakers.service.SessionAlarmService;
import fr.paug.androidmakers.ui.activity.DetailActivity;
import fr.paug.androidmakers.ui.adapter.AgendaPagerAdapter;
import fr.paug.androidmakers.ui.util.AgendaFilterMenu;
import fr.paug.androidmakers.ui.view.AgendaView;
import fr.paug.androidmakers.util.SessionSelector;
public class AgendaFragment extends Fragment implements AgendaView.AgendaClickListener,
AgendaFilterMenu.MenuFilterListener {
private AgendaFilterMenu mAgendaFilterMenu;
private View mProgressView;
private View mEmptyView;
private ViewPager mViewPager;
private AgendaView.AgendaSelector mAgendaSelector = new AgendaView.AgendaSelector() {
@Override
public boolean isSelected(int sessionId) {
return SessionSelector.getInstance().isSelected(sessionId);
}
@Override
public boolean hasSelected() {
return SessionSelector.getInstance().hasSelected();
}
};
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Keeps this Fragment alive during configuration changes
setRetainInstance(true);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_agenda, container, false);
mViewPager = (ViewPager) view.findViewById(R.id.viewpager);
mProgressView = view.findViewById(R.id.progressbar);
mEmptyView = view.findViewById(R.id.empty_view);
// auto dismiss loading
new Handler().postDelayed(new RefreshRunnable(this), 3000);
AgendaRepository.getInstance().load(new AgendaLoadListener(this));
setHasOptionsMenu(true);
return view;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
mAgendaFilterMenu = new AgendaFilterMenu(getContext(), menu, inflater);
mAgendaFilterMenu.setMenuFilterListener(this);
if (AgendaRepository.getInstance().isLoaded()) {
onAgendaLoaded(); // reload agenda
}
}
@Override
public void onResume() {
super.onResume();
PagerAdapter adapter = mViewPager.getAdapter();
if (adapter instanceof AgendaPagerAdapter) {
((AgendaPagerAdapter) adapter).refreshSessionsSelected();
}
}
@Override
public void onClick(AgendaView.Item agendaItem) {
DetailActivity.startActivity(getActivity(), agendaItem);
}
@Override
public void onFilterChanged() {
onAgendaLoaded();
}
private void onAgendaLoaded() {
if (mAgendaFilterMenu == null) {
return;
}
final String languageFilter = mAgendaFilterMenu.getLanguageFilter();
final Set<String> allLanguageAbreviated = AgendaRepository.getInstance().getAllLanguages();
final Set<String> fullLengthLanguageName = new HashSet<>();
for (final String languageAbbreviated : allLanguageAbreviated) {
final int languageStringRes = Session.getLanguageFullName(languageAbbreviated);
if (languageStringRes != 0) {
fullLengthLanguageName.add(getString(languageStringRes));
}
}
mAgendaFilterMenu.setLanguages(fullLengthLanguageName.toArray(new String[fullLengthLanguageName.size()]));
final SparseArray<AgendaView.DaySchedule> itemByDayOfTheYear = new SparseArray<>();
final Calendar calendar = Calendar.getInstance();
final List<ScheduleSlot> scheduleSlots = AgendaRepository.getInstance().getScheduleSlots();
for (final ScheduleSlot scheduleSlot : scheduleSlots) {
if (languageFilter != null) {
final int sessionId = scheduleSlot.sessionId;
final Session session = AgendaRepository.getInstance().getSession(sessionId);
if (session == null || session.getLanguageName() == 0 || !languageFilter.equals(getString(session.getLanguageName()))) {
// skip this session
continue;
}
}
final List<AgendaView.Item> agendaItems = getAgendaItems(
itemByDayOfTheYear, calendar, scheduleSlot);
agendaItems.add(new AgendaView.Item(scheduleSlot, getTitle(scheduleSlot.sessionId)));
}
final List<AgendaView.DaySchedule> items = getItemsOrdered(itemByDayOfTheYear);
final AgendaPagerAdapter adapter = new AgendaPagerAdapter(items, mAgendaSelector, this);
mViewPager.setAdapter(adapter);
final int indexOfToday = getTodayIndex(items);
if (indexOfToday > 0) {
mViewPager.setCurrentItem(indexOfToday, true);
}
refreshViewsDisplay();
adapter.refreshSessionsSelected();
}
private void refreshViewsDisplay() {
mProgressView.setVisibility(View.GONE);
PagerAdapter adapter = mViewPager.getAdapter();
if (adapter == null || adapter.getCount() == 0) {
mEmptyView.setVisibility(View.VISIBLE);
mViewPager.setVisibility(View.GONE);
} else {
mEmptyView.setVisibility(View.GONE);
mViewPager.setVisibility(View.VISIBLE);
}
}
private int getTodayIndex(List<AgendaView.DaySchedule> items) {
if (items == null || items.size() < 2) {
return -1;
}
Calendar calendar = Calendar.getInstance();
int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
int year = calendar.get(Calendar.YEAR);
for (int i = 1; i < items.size(); i++) {
AgendaView.DaySchedule agendaDaySchedule = items.get(i);
List<AgendaView.RoomSchedule> roomSchedules = agendaDaySchedule.getRoomSchedules();
if (!roomSchedules.isEmpty()) {
List<AgendaView.Item> itemList = roomSchedules.get(0).getItems();
if (!itemList.isEmpty()) {
AgendaView.Item item = itemList.get(0);
calendar.setTimeInMillis(item.getStartTimestamp());
if (calendar.get(Calendar.YEAR) == year
&& calendar.get(Calendar.DAY_OF_YEAR) == dayOfYear) {
return i;
}
}
}
}
return -1;
}
@NonNull
private List<AgendaView.Item> getAgendaItems(SparseArray<AgendaView.DaySchedule> itemByDayOfTheYear,
Calendar calendar, ScheduleSlot scheduleSlot) {
List<AgendaView.RoomSchedule> roomSchedules =
getRoomScheduleForDay(itemByDayOfTheYear, calendar, scheduleSlot);
AgendaView.RoomSchedule roomScheduleForThis = null;
for (AgendaView.RoomSchedule roomSchedule : roomSchedules) {
if (roomSchedule.getRoomId() == scheduleSlot.room) {
roomScheduleForThis = roomSchedule;
break;
}
}
if (roomScheduleForThis == null) {
List<AgendaView.Item> agendaItems = new ArrayList<>();
Room room = AgendaRepository.getInstance().getRoom(scheduleSlot.room);
String titleRoom = (room == null) ? null : room.name;
roomScheduleForThis = new AgendaView.RoomSchedule(
scheduleSlot.room, titleRoom, agendaItems);
roomSchedules.add(roomScheduleForThis);
Collections.sort(roomSchedules);
return agendaItems;
} else {
return roomScheduleForThis.getItems();
}
}
private List<AgendaView.RoomSchedule> getRoomScheduleForDay(
SparseArray<AgendaView.DaySchedule> itemByDayOfTheYear,
Calendar calendar, ScheduleSlot scheduleSlot) {
calendar.setTimeInMillis(scheduleSlot.startDate);
int dayIndex = calendar.get(Calendar.DAY_OF_YEAR) + calendar.get(Calendar.YEAR) * 1000;
AgendaView.DaySchedule daySchedule = itemByDayOfTheYear.get(dayIndex);
if (daySchedule == null) {
List<AgendaView.RoomSchedule> roomSchedule = new ArrayList<>();
String title = DateFormat.getDateInstance().format(calendar.getTime());
daySchedule = new AgendaView.DaySchedule(title, roomSchedule);
itemByDayOfTheYear.put(dayIndex, daySchedule);
return roomSchedule;
} else {
return daySchedule.getRoomSchedules();
}
}
@NonNull
private List<AgendaView.DaySchedule> getItemsOrdered(
SparseArray<AgendaView.DaySchedule> itemByDayOfTheYear) {
int size = itemByDayOfTheYear.size();
int[] keysSorted = new int[size];
for (int i = 0; i < size; i++) {
keysSorted[i] = itemByDayOfTheYear.keyAt(i);
}
Arrays.sort(keysSorted);
List<AgendaView.DaySchedule> items = new ArrayList<>(size);
for (int key : keysSorted) {
items.add(itemByDayOfTheYear.get(key));
}
return items;
}
private String getTitle(int sessionId) {
Session session = AgendaRepository.getInstance().getSession(sessionId);
return session == null ? "?" : session.title;
}
private static class RefreshRunnable implements Runnable {
private WeakReference<AgendaFragment> mAgendaActivity;
private RefreshRunnable(AgendaFragment agendaFragment) {
mAgendaActivity = new WeakReference<>(agendaFragment);
}
@Override
public void run() {
AgendaFragment agendaFragment = mAgendaActivity.get();
if (agendaFragment != null) {
agendaFragment.refreshViewsDisplay();
}
}
}
private static class AgendaLoadListener implements AgendaRepository.OnLoadListener {
private WeakReference<AgendaFragment> reference;
private AgendaLoadListener(AgendaFragment agendaFragment) {
reference = new WeakReference<>(agendaFragment);
}
@Override
public void onAgendaLoaded() {
AgendaFragment agendaFragment = reference.get();
if (agendaFragment == null) {
return;
}
agendaFragment.onAgendaLoaded();
final AgendaFragment fragment = reference.get();
if (fragment != null) {
// reschedule all starred blocks in case one session start or stop time has changed
final Context ctx = fragment.getContext();
Intent scheduleIntent = new Intent(
SessionAlarmService.ACTION_SCHEDULE_ALL_STARRED_BLOCKS,
null, ctx, SessionAlarmService.class);
ctx.startService(scheduleIntent);
}
}
}
}