package de.tum.in.tumcampusapp.fragments;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ToggleButton;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import de.tum.in.tumcampusapp.R;
import de.tum.in.tumcampusapp.auxiliary.CafeteriaPrices;
import de.tum.in.tumcampusapp.auxiliary.Const;
import de.tum.in.tumcampusapp.auxiliary.Utils;
import de.tum.in.tumcampusapp.cards.CafeteriaMenuCard;
import de.tum.in.tumcampusapp.managers.CafeteriaMenuManager;
import de.tum.in.tumcampusapp.managers.OpenHoursManager;
import de.tum.in.tumcampusapp.services.FavoriteDishReceiver;
/**
* Fragment for each cafeteria-page.
*/
public class CafeteriaDetailsSectionFragment extends Fragment {
private static final Pattern SPLIT_ANNOTATIONS_PATTERN = Pattern.compile("\\(([A-Za-z0-9]+),");
private static final Pattern NUMERICAL_ANNOTATIONS_PATTERN = Pattern.compile("\\(([1-9]|10|11)\\)");
/**
* Inflates the cafeteria menu layout.
* This is put into an extra static method to be able to
* reuse it in {@link CafeteriaMenuCard}
*
* @param rootView Parent layout
* @param cafeteriaId Cafeteria id
* @param dateStr Date in yyyy-mm-dd format
* @param big True to show big lines
*/
@SuppressLint("ShowToast")
public static List<View> showMenu(LinearLayout rootView, int cafeteriaId, String dateStr, boolean big) {
// initialize a few often used things
final Context context = rootView.getContext();
final Map<String, String> rolePrices = CafeteriaPrices.getRolePrices(context);
final int padding = (int) context.getResources().getDimension(R.dimen.card_text_padding);
List<View> addedViews = new ArrayList<>(32);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final CafeteriaMenuManager cmm = new CafeteriaMenuManager(context);
// Get menu items
Cursor cursorCafeteriaMenu = new CafeteriaMenuManager(context).getTypeNameFromDbCard(cafeteriaId, dateStr);
TextView textview;
if (!big) {
// Show opening hours
OpenHoursManager lm = new OpenHoursManager(context);
textview = new TextView(context);
textview.setText(lm.getHoursByIdAsString(context, cafeteriaId, Utils.getDate(dateStr)));
textview.setTextColor(ContextCompat.getColor(context, R.color.sections_green));
rootView.addView(textview);
addedViews.add(textview);
}
// Show cafeteria menu
String curShort = "";
if (cursorCafeteriaMenu.moveToFirst()) {
do {
String typeShort = cursorCafeteriaMenu.getString(3);
String typeLong = cursorCafeteriaMenu.getString(0);
final String menu = cursorCafeteriaMenu.getString(1);
// Skip unchecked categories if showing card
boolean shouldShow = Utils.getSettingBool(context, "card_cafeteria_" + typeShort,
"tg".equals(typeShort) || "ae".equals(typeShort));
if (!big && !shouldShow) {
continue;
}
// Add header if we start with a new category
if (!typeShort.equals(curShort)) {
curShort = typeShort;
View view = inflater.inflate(big ? R.layout.list_header_big : R.layout.card_list_header, rootView, false);
textview = (TextView) view.findViewById(R.id.list_header);
textview.setText(typeLong.replaceAll("[0-9]", "").trim());
rootView.addView(view);
addedViews.add(view);
}
// Show menu item
final SpannableString text = menuToSpan(context, big ? menu : prepare(menu));
if (rolePrices.containsKey(typeLong)) {
// If price is available
View view = inflater.inflate(big ? R.layout.price_line_big : R.layout.card_price_line, rootView, false);
textview = (TextView) view.findViewById(R.id.line_name);
TextView priceView = (TextView) view.findViewById(R.id.line_price);
final ToggleButton favDish = (ToggleButton) view.findViewById(R.id.favortieDish);
favDish.setTag(menu + "__" + cafeteriaId);
/**
* saved dish id in the favoriteDishButton tag.
* onButton checked getTag->DishID and mark it as favorite locally (favorite=1)
*/
textview.setText(text);
priceView.setText(String.format("%s €", rolePrices.get(typeLong)));
rootView.addView(view);
addedViews.add(view);
Cursor c = cmm.checkIfFavoriteDish(favDish.getTag().toString());
if (c.getCount() > 0) {
if (!favDish.isChecked()) {
favDish.setChecked(true);
}
} else {
if (favDish.isChecked()) {
favDish.setChecked(false);
}
}
View.OnClickListener favoriteToggleButtonListener = new View.OnClickListener() {
@Override
public void onClick(View view) {
String id = view.getTag().toString();
String[] data = id.split("__");
String dishname = data[0];
int mensaId = Integer.parseInt(data[1]);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(context, FavoriteDishReceiver.class);
if (((ToggleButton) view).isChecked()) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
String currentDate = DateTime.now().toString(formatter);
Cursor c = cmm.getFavoriteDishNextDates(mensaId, dishname);
cmm.insertFavoriteDish(mensaId, dishname, currentDate, favDish.getTag().toString());
if (c.getCount() > 0) {
while (c.moveToNext()) {
cmm.insertFavoriteDish(mensaId, dishname, c.getString(0), favDish.getTag().toString());
Cursor cur = cmm.getLastInsertedDishId(mensaId, dishname);
DateTime dt = formatter.parseDateTime(c.getString(0)).withHourOfDay(9);
long millsToAlarm = dt.getMillis() - DateTime.now().getMillis();
int alertID = 0;
if (cur.moveToFirst()) {
alertID = cur.getInt(0);
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, alertID, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millsToAlarm, pendingIntent);
}
}
} else {
Cursor curs = cmm.getFavoriteDishAllIds(mensaId, dishname);
while (curs.moveToNext()) {
int alertId = curs.getInt(0);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, alertId, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
pendingIntent.cancel();
alarmManager.cancel(pendingIntent);
}
cmm.deleteFavoriteDish(mensaId, dishname);
}
}
};
favDish.setOnClickListener(favoriteToggleButtonListener);
} else {
// Without price
textview = new TextView(context);
textview.setText(text);
textview.setPadding(padding, padding, padding, padding);
rootView.addView(textview);
addedViews.add(textview);
}
} while (cursorCafeteriaMenu.moveToNext());
}
cursorCafeteriaMenu.close();
return addedViews;
}
/**
* Converts menu text to {@link SpannableString}.
* Replaces all (v), ... annotations with images
*
* @param context Context
* @param menu Text with annotations
* @return Spannable text with images
*/
public static SpannableString menuToSpan(Context context, String menu) {
final String processedMenu = splitAnnotations(menu);
final SpannableString text = new SpannableString(processedMenu);
replaceWithImg(context, processedMenu, text, "(v)", R.drawable.meal_vegan);
replaceWithImg(context, processedMenu, text, "(f)", R.drawable.meal_veggie);
replaceWithImg(context, processedMenu, text, "(R)", R.drawable.meal_beef);
replaceWithImg(context, processedMenu, text, "(S)", R.drawable.meal_pork);
replaceWithImg(context, processedMenu, text, "(GQB)", R.drawable.ic_gqb);
replaceWithImg(context, processedMenu, text, "(99)", R.drawable.meal_alcohol);
return text;
}
private static void replaceWithImg(Context context, String menu, SpannableString text, String sym, int drawable) {
int ind = menu.indexOf(sym);
while (ind >= 0) {
ImageSpan is = new ImageSpan(context, drawable);
text.setSpan(is, ind, ind + sym.length(), 0);
ind = menu.indexOf(sym, ind + sym.length());
}
}
/**
* Replaces all annotations that cannot be replaces with images such as (1), ...
*
* @param menu Text to delete annotations from
* @return Text without un-replaceable annotations
*/
private static String prepare(String menu) {
final String tmp = splitAnnotations(menu);
return NUMERICAL_ANNOTATIONS_PATTERN.matcher(tmp).replaceAll("");
}
@NonNull
private static String splitAnnotations(String menu) {
int len;
String tmp = menu;
do {
len = tmp.length();
tmp = SPLIT_ANNOTATIONS_PATTERN.matcher(tmp).replaceFirst("($1)(");
} while (tmp.length() > len);
return tmp;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_cafeteriadetails_section, container, false);
LinearLayout root = (LinearLayout) rootView.findViewById(R.id.layout);
int cafeteriaId = getArguments().getInt(Const.CAFETERIA_ID);
String date = getArguments().getString(Const.DATE);
showMenu(root, cafeteriaId, date, true);
return rootView;
}
}