gt:                         String names[] = getUpdatedRoutineNames();
context: /*
   *    Calendula - An assistant for personal medication management.
   *    Copyright (C) 2014-2018 CiTIUS - University of Santiago de Compostela
   *
   *    Calendula is free software; you can redistribute it and/or modify
   *    it under the terms of the GNU General Public License as published by
   *    the Free Software Foundation; either version 3 of the License, or
   *    (at your option) any later version.
   *
   *    This program is distributed in the hope that it will be useful,
   *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *    GNU General Public License for more details.
   *
   *    You should have received a copy of the GNU General Public License
   *    along with this software.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package es.usc.citius.servando.calendula.fragments;
  
  import android.annotation.SuppressLint;
  import android.app.AlertDialog;
  import android.app.DatePickerDialog;
  import android.content.ContextWrapper;
  import android.content.DialogInterface;
  import android.content.res.Resources;
  import android.graphics.Color;
  import android.graphics.Typeface;
  import android.graphics.drawable.GradientDrawable;
  import android.graphics.drawable.StateListDrawable;
  import android.os.Bundle;
  import android.support.annotation.NonNull;
  import android.support.v4.app.Fragment;
  import android.support.v4.app.FragmentManager;
  import android.text.Html;
  import android.text.Spanned;
  import android.text.format.Time;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.MotionEvent;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.animation.Animation;
  import android.view.animation.AnimationUtils;
  import android.widget.AdapterView;
  import android.widget.ArrayAdapter;
  import android.widget.Button;
  import android.widget.DatePicker;
  import android.widget.ImageButton;
  import android.widget.LinearLayout;
  import android.widget.NumberPicker;
  import android.widget.ScrollView;
  import android.widget.Spinner;
  import android.widget.TextView;
  
  import com.codetroopers.betterpickers.numberpicker.NumberPickerBuilder;
  import com.codetroopers.betterpickers.numberpicker.NumberPickerDialogFragment;
  import com.codetroopers.betterpickers.radialtimepicker.RadialTimePickerDialogFragment;
  import com.codetroopers.betterpickers.recurrencepicker.EventRecurrence;
  import com.codetroopers.betterpickers.recurrencepicker.RecurrencePickerDialogFragment;
  import com.google.ical.values.DateTimeValueImpl;
  import com.google.ical.values.DateValue;
  import com.google.ical.values.Frequency;
  
  import org.joda.time.DateTime;
  import org.joda.time.LocalDate;
  import org.joda.time.LocalTime;
  
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collections;
  import java.util.IllegalFormatConversionException;
  import java.util.List;
  
  import es.usc.citius.servando.calendula.R;
  import es.usc.citius.servando.calendula.activities.ScheduleCreationActivity;
  import es.usc.citius.servando.calendula.database.DB;
  import es.usc.citius.servando.calendula.fragments.dosePickers.DefaultDosePickerFragment;
  import es.usc.citius.servando.calendula.fragments.dosePickers.DosePickerFragment;
  import es.usc.citius.servando.calendula.fragments.dosePickers.LiquidDosePickerFragment;
  import es.usc.citius.servando.calendula.fragments.dosePickers.PillDosePickerFragment;
  import es.usc.citius.servando.calendula.persistence.Medicine;
  import es.usc.citius.servando.calendula.persistence.Patient;
  import es.usc.citius.servando.calendula.persistence.Presentation;
  import es.usc.citius.servando.calendula.persistence.RepetitionRule;
  import es.usc.citius.servando.calendula.persistence.Routine;
  import es.usc.citius.servando.calendula.persistence.Schedule;
  import es.usc.citius.servando.calendula.persistence.ScheduleItem;
  import es.usc.citius.servando.calendula.persistence.ScheduleItemComparator;
  import es.usc.citius.servando.calendula.util.LogUtil;
  import es.usc.citius.servando.calendula.util.ScheduleHelper;
  import es.usc.citius.servando.calendula.util.Snack;
  
  public class ScheduleTimetableFragment extends Fragment
          implements NumberPickerDialogFragment.NumberPickerDialogHandlerV2,
          RecurrencePickerDialogFragment.OnRecurrenceSetListener, RadialTimePickerDialogFragment.OnTimeSetListener {
  
      public static final int REF_DIALOG_HOURLY_INTERVAL = 1;
      public static final int REF_DIALOG_ROUTINE_INTERVAL = 2;
      public static final int REF_DIALOG_CYCLE_DAYS = 3;
      public static final int REF_DIALOG_CYCLE_REST = 4;
      private static final String TAG = "ScheduleTimetableFragm";
      final Frequency[] FREQ =
              new Frequency[]{Frequency.DAILY, Frequency.WEEKLY, Frequency.MONTHLY};
  
      LinearLayout timetableContainer;
      int timesPerDay = 1;
  
      int cycleDays = -1;
      int cycleRest = -1;
  
      Spinner scheduleSpinner;
      Spinner repeatTypeSpinner;
      Spinner freqSpinner;
      ScheduleItemComparator scheduleItemComparator = new ScheduleItemComparator();
  
      Button buttonScheduleStart;
      Button buttonScheduleEnd;
      Button intervalEditText;
      Button hourlyIntervalEditText;
      Button hourlyIntervalFrom;
      Button hourlyIntervalRepeatDose;
  
      Button periodValue;
      Button periodRest;
  
      ImageButton cycleSpinnerTrigger;
  
      //RadioGroup scheduleTypeRadioGroup;
  
      ImageButton clearStartButton;
      ImageButton clearEndButton;
  
      View daySelectionBox;
      View customRepeatBox;
      TextView ruleText;
  
      Schedule schedule;
      boolean ignoreNextEvent = true;
  
      //View boxType;
      View boxHourlyInterval;
      View boxTimesByDay;
      View boxTimetable;
      View boxRepeat;
      View boxPeriod;
      View boxDuration;
      View boxHelp;
  
      TextView helpView;
      ImageButton nextButton;
      ScrollView scrollView;
      int color;
      private boolean isFirstScheduleSelection = true;
      private int lastScheduleType = -1;
      private Patient patient;
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          // get schedule from state helper if any
          schedule = ScheduleHelper.instance().getSchedule();
  
          if (schedule == null) {
              schedule = new Schedule();
              ScheduleHelper.instance().setSchedule(schedule);
          }
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          View rootView = inflater.inflate(R.layout.fragment_schedule_timetable, container, false);
          patient = DB.patients().getActive(getActivity());
          color = patient.getColor();
          scrollView = (ScrollView) rootView.findViewById(R.id.schedule_scroll);
          timetableContainer =
                  (LinearLayout) rootView.findViewById(R.id.schedule_timetable_container);
          boxHourlyInterval = rootView.findViewById(R.id.box_hourinterval);
          boxTimesByDay = rootView.findViewById(R.id.box_schedule_times_by_day);
          boxTimetable = rootView.findViewById(R.id.box_schedule_timetable);
          boxRepeat = rootView.findViewById(R.id.box_schedule_repeat);
          boxPeriod = rootView.findViewById(R.id.box_schedule_period);
          boxDuration = rootView.findViewById(R.id.box_schedule_duration);
          boxHelp = rootView.findViewById(R.id.box_schedule_help);
          helpView = (TextView) rootView.findViewById(R.id.schedule_help_text);
          nextButton = (ImageButton) rootView.findViewById(R.id.schedule_help_button);
          hourlyIntervalEditText = (Button) rootView.findViewById(R.id.hourinterval_edit_text);
          hourlyIntervalFrom = (Button) rootView.findViewById(R.id.hourinterval_from_text);
          hourlyIntervalRepeatDose = (Button) rootView.findViewById(R.id.repeat_dose);
          scheduleSpinner = (Spinner) rootView.findViewById(R.id.schedules_spinner);
          buttonScheduleStart = (Button) rootView.findViewById(R.id.button_set_start);
          buttonScheduleEnd = (Button) rootView.findViewById(R.id.button_set_end);
          clearStartButton = (ImageButton) rootView.findViewById(R.id.button_clear_start);
          clearEndButton = (ImageButton) rootView.findViewById(R.id.button_clear_end);
          repeatTypeSpinner = (Spinner) rootView.findViewById(R.id.repeat_type_spinner);
  
          periodValue = (Button) rootView.findViewById(R.id.period_value);
          periodRest = (Button) rootView.findViewById(R.id.period_rest);
  
          freqSpinner = (Spinner) rootView.findViewById(R.id.freq_spinner);
          daySelectionBox = rootView.findViewById(R.id.day_selector_box);
          customRepeatBox = rootView.findViewById(R.id.custom_repeat_box);
          intervalEditText = (Button) rootView.findViewById(R.id.interval_edit_text);
          ruleText = (TextView) rootView.findViewById(R.id.rule_text);
          cycleSpinnerTrigger = (ImageButton) rootView.findViewById(R.id.cycles_spinner_trigger);
  
          setupScheduleSpinner();
          setupDaySelectionListeners(rootView);
          setupHourlyRepetitionListeners();
          setupStartEndDatePickers(rootView);
          setupForCurrentSchedule(rootView);
          setupCycleSpinner();
  
          setupForCurrentSchedule(rootView);
          updateColors(rootView);
  
          return rootView;
      }
  
      public void onTypeSelected() {
          LogUtil.d(TAG, "onTypeSelected");
          if (getView() != null) {
              LogUtil.d(TAG, "getView() is not null");
              setupForCurrentSchedule(getView());
          }
      }
  
      public void onViewCreated(View view, Bundle savedInstanceState) {
          super.onViewCreated(view, savedInstanceState);
      }
  
      @Override
      public void onResume() {
          super.onResume();
      }
  
  
      @Override
      public void onRecurrenceSet(String s) {
  
          EventRecurrence event = new EventRecurrence();
  
          LocalDate now = LocalDate.now();
          Time startDate = new Time(Time.getCurrentTimezone());
          startDate.set(now.getDayOfMonth(), now.getMonthOfYear(), now.getYear());
          startDate.normalize(true);
          event.parse(s);
          event.setStartDate(startDate);
  
          LogUtil.d(TAG, "OnRecurrenceSet: " + event.startDate);
  
          schedule.setRepetition(new RepetitionRule("RRULE:" + s));
          setScheduleStart(schedule.start());
          LocalDate end = schedule.end();
          LogUtil.d(TAG, "ICAL: " + schedule.rule().toIcal());
          setScheduleEnd(end);
          LogUtil.d(TAG, "ICAL: " + schedule.rule().toIcal());
          ruleText.setText(getCurrentSchedule());
      }
  
      @Override
      public void onDialogNumberSet(int reference, BigInteger number, double decimal, boolean isNegative, BigDecimal fullNumber) {
          final int numberValue = number.intValue();
          if (reference == REF_DIALOG_ROUTINE_INTERVAL) {
              intervalEditText.setText(Integer.toString(numberValue));
              schedule.rule().setInterval(numberValue);
          } else if (reference == REF_DIALOG_HOURLY_INTERVAL) {
              hourlyIntervalEditText.setText(Integer.toString(numberValue));
              schedule.rule().setFrequency(Frequency.HOURLY);
              schedule.rule().setInterval(numberValue);
          } else if (reference == REF_DIALOG_CYCLE_DAYS) {
              periodValue.setText(String.valueOf(number));
              cycleDays = numberValue;
              if (cycleRest > 0) {
                  schedule.setCycle(cycleDays, cycleRest);
              }
          } else if (reference == REF_DIALOG_CYCLE_REST) {
              periodRest.setText(String.valueOf(number));
              cycleRest = numberValue;
              if (cycleDays > 0) {
                  schedule.setCycle(cycleDays, cycleRest);
              }
          }
      }
  
      @Override
      public void onTimeSet(RadialTimePickerDialogFragment dialog, int hour, int minute) {
          String time = new LocalTime(hour, minute).toString("HH:mm");
          hourlyIntervalFrom.setText(getString(R.string.first_intake) + ": " + time);
          schedule.setStartTime(new LocalTime(hour, minute));
      }
  
      void setupHourlyRepetitionListeners() {
          hourlyIntervalEditText.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  showHourlyPickerDIalog();
              }
          });
  
          hourlyIntervalFrom.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
  
                  DateTime time = schedule.startTime().toDateTimeToday();
  
                  RadialTimePickerDialogFragment timePickerDialog =
                          new RadialTimePickerDialogFragment()
                                  .setOnTimeSetListener(ScheduleTimetableFragment.this)
                                  .setStartTime(time.getHourOfDay(), time.getMinuteOfHour());
                  timePickerDialog.show(getActivity().getSupportFragmentManager(), "111");
              }
          });
  
          hourlyIntervalRepeatDose.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  showHourlyDosePickerDialog();
              }
          });
      }
  
      void setupStartEndDatePickers(View rootView) {
  
          /*
           * Needed to fix crashes on samsung 5.0 devices.
           *
           * See: https://stackoverflow.com/q/28618405/4243049
           */
          final ContextWrapper datePickerContext = new ContextWrapper(getActivity()) {
  
              private Resources wrappedResources;
  
              @Override
              public Resources getResources() {
                  Resources r = super.getResources();
                  if (wrappedResources == null) {
                      wrappedResources = new Resources(r.getAssets(), r.getDisplayMetrics(), r.getConfiguration()) {
                          @NonNull
                          @Override
                          public String getString(int id, Object... formatArgs) throws NotFoundException {
                              try {
                                  return super.getString(id, formatArgs);
                              } catch (IllegalFormatConversionException e) {
                                  Log.w(TAG, "Trying to fix resource exception", e);
                                  String template = super.getString(id);
                                  template = template.replaceAll("%" + e.getConversion(), "%s");
                                  return String.format(getConfiguration().locale, template, formatArgs);
                              }
                          }
                      };
                  }
                  return wrappedResources;
              }
          };
  
          if (schedule.start() == null) {
              schedule.setStart(LocalDate.now());
          }
  
          final LocalDate scheduleStart = schedule.start();
  
          buttonScheduleStart.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
  
                  DatePickerDialog dpd =
                          new DatePickerDialog(datePickerContext, new DatePickerDialog.OnDateSetListener() {
                              @Override
                              public void onDateSet(DatePicker view, int year, int monthOfYear,
                                                    int dayOfMonth) {
                                  LogUtil.d(TAG, year + " " + monthOfYear);
                                  LocalDate d = new LocalDate(year, monthOfYear + 1, dayOfMonth);
                                  setScheduleStart(d);
                              }
                          }, scheduleStart.getYear(), scheduleStart.getMonthOfYear() - 1,
                                  scheduleStart.getDayOfMonth());
                  dpd.show();
              }
          });
  
          buttonScheduleEnd.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
  
                  LocalDate scheduleEnd =
                          schedule.end() != null ? schedule.end() : scheduleStart.plusMonths(3);
  
                  DatePickerDialog dpd =
                          new DatePickerDialog(datePickerContext, new DatePickerDialog.OnDateSetListener() {
                              @Override
                              public void onDateSet(DatePicker view, int year, int monthOfYear,
                                                    int dayOfMonth) {
                                  LocalDate d = new LocalDate(year, monthOfYear + 1, dayOfMonth);
                                  setScheduleEnd(d);
                              }
                          }, scheduleEnd.getYear(), scheduleEnd.getMonthOfYear() - 1,
                                  scheduleEnd.getDayOfMonth());
                  dpd.show();
              }
          });
  
          buttonScheduleEnd.setOnLongClickListener(new View.OnLongClickListener() {
              @Override
              public boolean onLongClick(View v) {
                  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                  builder.setMessage(R.string.schedule_continue_indefinitely)
                          .setCancelable(true)
                          .setPositiveButton(getString(R.string.dialog_yes_option),
                                  new DialogInterface.OnClickListener() {
                                      public void onClick(DialogInterface dialog, int id) {
                                          setScheduleEnd(null);
                                      }
                                  })
                          .setNegativeButton(getString(R.string.dialog_no_option),
                                  new DialogInterface.OnClickListener() {
                                      public void onClick(DialogInterface dialog, int id) {
                                          dialog.cancel();
                                      }
                                  });
                  AlertDialog alert = builder.create();
                  alert.show();
                  return true;
              }
          });
  
          clearStartButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  setScheduleStart(null);
              }
          });
  
          clearEndButton.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  setScheduleEnd(null);
              }
          });
  
          setScheduleStart(schedule.start());
          setScheduleEnd(schedule.end());
      }
  
      void onScheduleSelected(String selection, int index) {
  
          ScheduleHelper.instance().setSelectedScheduleIdx(index);
          String schedules[] = getResources().getStringArray(R.array.schedules_array);
  
          // obtain times per day from selected schedule
          for (int i = 0; i < schedules.length; i++) {
              if (schedules[i].equalsIgnoreCase(selection)) {
                  timesPerDay = i + 1;
                  ScheduleHelper.instance().setTimesPerDay(timesPerDay);
                  break;
              }
          }
          addTimetableEntries(timesPerDay, DB.routines().findAllForActivePatient(getContext()));
      }
  
      void setupDaySelectionListeners(final View rootView) {
  
          View.OnClickListener listener = new View.OnClickListener() {
              @Override
              public void onClick(View view) {
  
                  TextView text = ((TextView) view);
                  int index;
                  switch (text.getId()) {
                      case R.id.day_mo:
                          schedule.toggleSelectedDay(0);
                          index = 0;
                          break;
                      case R.id.day_tu:
                          schedule.toggleSelectedDay(1);
                          index = 1;
                          break;
                      case R.id.day_we:
                          schedule.toggleSelectedDay(2);
                          index = 2;
                          break;
                      case R.id.day_th:
                          index = 3;
                          schedule.toggleSelectedDay(3);
                          break;
                      case R.id.day_fr:
                          schedule.toggleSelectedDay(4);
                          index = 4;
                          break;
                      case R.id.day_sa:
                          schedule.toggleSelectedDay(5);
                          index = 5;
                          break;
                      case R.id.day_su:
                          schedule.toggleSelectedDay(6);
                          index = 6;
                          break;
                      default:
                          return;
                  }
  
                  boolean daySelected = schedule.days()[index];
                  StateListDrawable sld = (StateListDrawable) text.getBackground();
                  GradientDrawable shape = (GradientDrawable) sld.getCurrent();
                  shape.setColor(daySelected ? color : Color.WHITE);
                  text.setTypeface(null, daySelected ? Typeface.BOLD : Typeface.NORMAL);
                  text.setTextColor(daySelected ? Color.WHITE : Color.BLACK);
  
                  boolean allDaysSelected = schedule.allDaysSelected();
  
                  if (schedule.type() == Schedule.SCHEDULE_TYPE_EVERYDAY && !allDaysSelected) {
                      setRepeatType(Schedule.SCHEDULE_TYPE_SOMEDAYS, rootView, false);
                      ignoreNextEvent = true;
                      repeatTypeSpinner.setSelection(1);
                  } else if (schedule.type() == Schedule.SCHEDULE_TYPE_SOMEDAYS && allDaysSelected) {
                      repeatTypeSpinner.setSelection(0);
                      schedule.setType(Schedule.SCHEDULE_TYPE_EVERYDAY);
                  }
  
                  LogUtil.d(TAG, "All days selected: " + allDaysSelected + ", repeatType: " + schedule.type());
              }
          };
  
          rootView.findViewById(R.id.day_mo).setOnClickListener(listener);
          rootView.findViewById(R.id.day_tu).setOnClickListener(listener);
          rootView.findViewById(R.id.day_we).setOnClickListener(listener);
          rootView.findViewById(R.id.day_th).setOnClickListener(listener);
          rootView.findViewById(R.id.day_fr).setOnClickListener(listener);
          rootView.findViewById(R.id.day_sa).setOnClickListener(listener);
          rootView.findViewById(R.id.day_su).setOnClickListener(listener);
      }
  
      void showIntervalPickerDIalog() {
          NumberPickerBuilder npb =
                  new NumberPickerBuilder().setDecimalVisibility(NumberPicker.INVISIBLE)
                          .setMinNumber(BigDecimal.ONE)
                          .setMaxNumber(BigDecimal.valueOf(31))
                          .setPlusMinusVisibility(NumberPicker.INVISIBLE)
                          .setFragmentManager(getActivity().getSupportFragmentManager())
                          .setTargetFragment(this).setReference(REF_DIALOG_ROUTINE_INTERVAL)
                          .setStyleResId(R.style.BetterPickersDialogFragment_Calendula);
          npb.show();
      }
  
      void showHourlyPickerDIalog() {
  
          AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
          b.setTitle(getString(R.string.dialog_interval_title));
  
          final int[] hourlyRepValues = getContext().getResources().getIntArray(R.array.hourly_repetition_values);
  //        final String[] hourlyRepDisplay = getContext().getResources().getStringArray(R.array.hourly_repetition_display);
  
          b.setItems(R.array.hourly_repetition_display, new DialogInterface.OnClickListener() {
  
              @SuppressLint("SetTextI18n")
              //the int is put into a button with just the value, no need for localization
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  dialog.dismiss();
                  final int result = hourlyRepValues[which];
                  hourlyIntervalEditText.setText(Integer.toString(result));
                  schedule.rule().setFrequency(Frequency.HOURLY);
                  schedule.rule().setInterval(result);
              }
          });
  
          b.show();
  
  
      }
  
      void showRecurrencePickerDialog() {
          RecurrencePickerDialogFragment dialog = new RecurrencePickerDialogFragment();
  
          DateTime start = schedule.start() != null ? schedule.start().toDateTimeAtStartOfDay()
                  : DateTime.now().withTimeAtStartOfDay();
  
          Bundle b = new Bundle();
  
          b.putString(RecurrencePickerDialogFragment.BUNDLE_RRULE,
                  schedule.rule().toIcal().replace("RRULE:", ""));
          b.putLong(RecurrencePickerDialogFragment.BUNDLE_START_TIME_MILLIS, DateTime.now().getMillis());
          //b.putString(RecurrencePickerDialog.BUNDLE_TIME_ZONE, t.timezone);
  
          dialog.setArguments(b);
          dialog.setOnRecurrenceSetListener(this);
          dialog.show(getActivity().getSupportFragmentManager(), "REC");
      }
  
      void addTimetableEntries(int timesPerDay, List<Routine> routines) {
  
          Collections.sort(ScheduleHelper.instance().getScheduleItems(), scheduleItemComparator);
  
          LinearLayout.LayoutParams params =
                  new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                          LinearLayout.LayoutParams.WRAP_CONTENT);
  
          String[] routineNames = getUpdatedRoutineNames();
          timetableContainer.removeAllViews();
  
          List<ScheduleItem> scheduleItems = new ArrayList<>();
  
          boolean enableDelete = timesPerDay > 1;
  
          for (int i = 0; i < timesPerDay; i++) {
              // try to get previous routine from state holder
              ScheduleItem s;
  
              if (i < ScheduleHelper.instance().getScheduleItems().size()) {
                  ScheduleItem toCopy = ScheduleHelper.instance().getScheduleItems().get(i);
                  s = new ScheduleItem(null, toCopy.getRoutine(), toCopy.getDose());
              } else {
                  s = new ScheduleItem(null, (i < routines.size()) ? routines.get(i) : null, 1);
              }
  
              if (s != null) {
                  scheduleItems.add(s);
              }
  
              View view = buildTimetableEntry(s, routineNames, enableDelete);
              timetableContainer.addView(view, params);
          }
  
          ScheduleHelper.instance().setScheduleItems(scheduleItems);
  
          //        for (ScheduleItem i : ScheduleCreationHelper.instance().getScheduleItems())
          //            LogUtil.d(TAG, "addTimetableEntries (end): " + i.getId() + ", " + i.routine().name() + ", " + i.dose());
  
      }
  
      String[] getUpdatedRoutineNames() {
  
          List<Routine> routines = DB.routines().findAllForActivePatient(getContext());
  
          int j = 0;
          String[] routineNames = new String[routines.size() + 1];
          for (Routine r : routines) {
              routineNames[j++] = r.getName();
          }
  
          routineNames[routineNames.length - 1] = getString(R.string.create_new_routine);
  
          return routineNames;
      }
  
      View buildTimetableEntry(ScheduleItem r, String[] routineNames, boolean enableDelete) {
          LayoutInflater inflater = getActivity().getLayoutInflater();
          final View entry = inflater.inflate(R.layout.schedule_timetable_entry, null);
          updateEntryTime(r.getRoutine(), entry);
          setupScheduleEntrySpinners(entry, r, routineNames);
  
          if (enableDelete) {
              entry.findViewById(R.id.entry_remove).setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View view) {
                      ScheduleHelper.instance()
                              .getScheduleItems()
                              .remove(timetableContainer.indexOfChild(entry));
                      scheduleSpinner.setSelection(timesPerDay - 2);
                  }
              });
          } else {
              entry.findViewById(R.id.entry_remove).setVisibility(View.INVISIBLE);
          }
          return entry;
      }
  
      void updateRoutineSelectionAdapter(final View entryView, Spinner routineSpinner,
                                         String[] routineNames) {
          ArrayAdapter<String> routineAdapter =
                  new ArrayAdapter<>(getActivity(), android.R.layout.simple_spinner_item,
                          routineNames);
          routineAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
          routineSpinner.setAdapter(routineAdapter);
      }
  
      void updateEntryTime(Routine r, View entry) {
          String hourText;
          String minuteText;
          if (r != null) {
              hourText = (r.getTime().getHourOfDay() < 10 ? "0" + r.getTime().getHourOfDay()
                      : r.getTime().getHourOfDay()) + ":";
              minuteText = (r.getTime().getMinuteOfHour() < 10 ? "0" + r.getTime().getMinuteOfHour()
                      : r.getTime().getMinuteOfHour()) + "";
          } else {
              hourText = "--:";
              minuteText = "--";
          }
  
          TextView h = ((TextView) entry.findViewById(R.id.hour_text));
          TextView m = ((TextView) entry.findViewById(R.id.minute_text));
          h.setText(hourText);
          m.setText(minuteText);
          h.setTextColor(color);
          m.setTextColor(color);
      }
  
      void showAddNewRoutineDialog(final View entryView) {
          FragmentManager fm = getActivity().getSupportFragmentManager();
          final RoutineCreateOrEditFragment addRoutineFragment = new RoutineCreateOrEditFragment();
          addRoutineFragment.setOnRoutineEditListener(
                  new RoutineCreateOrEditFragment.OnRoutineEditListener() {
                      @Override
                      public void onRoutineEdited(Routine r) {
                          // do nothing
                      }
  
                      @Override
                      public void onRoutineDeleted(Routine r) {
                          // do nothing
                      }
  
                      @Override
                      public void onRoutineCreated(final Routine r) {
                          Spinner rSpinner = (Spinner) entryView.findViewById(R.id.entry_routine_spinner);
  