es.usc.citius.servando.calendula.fragments.ScheduleImportFragment.java Source code

Java tutorial

Introduction

Here is the source code for es.usc.citius.servando.calendula.fragments.ScheduleImportFragment.java

Source

/*
 *    Calendula - An assistant for personal medication management.
 *    Copyright (C) 2016 CITIUS - USC
 *
 *    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.app.AlertDialog;
import android.app.DatePickerDialog;
import android.content.DialogInterface;
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.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.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.NumberPicker;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;

import com.doomonafireball.betterpickers.numberpicker.NumberPickerBuilder;
import com.doomonafireball.betterpickers.numberpicker.NumberPickerDialogFragment;
import com.doomonafireball.betterpickers.radialtimepicker.RadialTimePickerDialog;
import com.doomonafireball.betterpickers.recurrencepicker.EventRecurrence;
import com.doomonafireball.betterpickers.recurrencepicker.RecurrencePickerDialog;
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.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import es.usc.citius.servando.calendula.R;
import es.usc.citius.servando.calendula.activities.ConfirmSchedulesActivity;
import es.usc.citius.servando.calendula.activities.qrWrappers.PrescriptionWrapper;
import es.usc.citius.servando.calendula.activities.qrWrappers.ScheduleWrapper;
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.HomogeneousGroup;
import es.usc.citius.servando.calendula.persistence.Medicine;
import es.usc.citius.servando.calendula.persistence.Prescription;
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;

/**
 * Created by joseangel.pineiro on 12/11/13.
 */
public class ScheduleImportFragment extends Fragment
        implements NumberPickerDialogFragment.NumberPickerDialogHandler,
        RecurrencePickerDialog.OnRecurrenceSetListener, RadialTimePickerDialog.OnTimeSetListener {

    public static final String TAG = ScheduleImportFragment.class.getName();

    public static final String ARG_PRESCRIPTION = "ARG_PRESCRIPTION";

    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;

    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;
    LinearLayout changeList;
    Button continueButton;

    View boxScheduleChangedMsg;
    View newScheduleBox;

    TextView helpView;
    ImageButton nextButton;
    ScrollView scrollView;

    PrescriptionWrapper prescriptionWrapper;
    float doses[] = new float[] { 1f };
    public int selectedScheduleIdx;
    List<ScheduleItem> sItems = new ArrayList<>();
    private boolean hasChanges = false;
    private boolean isNew;
    private List<String> changes;
    private boolean hasEnd;
    private int daysToEnd;

    int color;

    public static ScheduleImportFragment newInstance(PrescriptionWrapper pw) {
        ScheduleImportFragment fragment = new ScheduleImportFragment();
        Bundle args = new Bundle();
        args.putSerializable(ARG_PRESCRIPTION, pw.holder());
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        color = DB.patients().getActive(getActivity()).color();
        PrescriptionWrapper.Holder h = (PrescriptionWrapper.Holder) getArguments()
                .getSerializable(ARG_PRESCRIPTION);
        prescriptionWrapper = PrescriptionWrapper.from(h);

        if (prescriptionWrapper != null && prescriptionWrapper.s != null
                && (prescriptionWrapper.cn != null || prescriptionWrapper.g != null)) {
            Log.d(TAG, "Wrapper: " + prescriptionWrapper.cn + "," + (prescriptionWrapper.s.d));
            updatePrescriptionValues();
            Schedule s = findByPrescriptionWrapper(prescriptionWrapper);
            if (s != null) {
                schedule = s;
                sItems = schedule.items();
                if (sItems == null) {
                    sItems = new ArrayList<>();
                }
                setNew(false);
                // changes = changes(s, prescriptionWrapper);
            } else {
                setNew(true);
                // changes = changes(s, prescriptionWrapper);
                Log.d(TAG, "Schedule not found found");
            }
        }

    }

    private void updatePrescriptionValues() {
        ScheduleWrapper sw = prescriptionWrapper.s;

        Log.d(TAG, "UpdatePrescriptionValues: " + prescriptionWrapper.g + ", " + sw.p + ", " + sw.d + ", " + sw.i);

        if (sw.p != -1) {
            int times = 24 / sw.p;
            float dose = sw.d; //   dose / times ?
            timesPerDay = times;
            doses = new float[timesPerDay];
            for (int i = 0; i < doses.length; i++) {
                doses[i] = dose > 0 ? dose : 1;
            }
            Log.d(TAG, " Values: " + timesPerDay + ", " + dose);
        } else if (sw.i != -1) {
            hasEnd = true;
            daysToEnd = sw.i;
            float dose = sw.d; //   dose / times ?
            timesPerDay = 1;
            doses = new float[timesPerDay];
            for (int i = 0; i < doses.length; i++) {
                doses[i] = dose > 0 ? dose : 1;
            }
        } else {
            Log.d(TAG, "Period not avilable");
        }

        Log.d(TAG,
                "Updated prescription values "
                        + (prescriptionWrapper.g != null ? prescriptionWrapper.g : prescriptionWrapper.cn) + ","
                        + timesPerDay + ", " + Arrays.toString(doses));
    }

    public void changeScheduleType(int type) {

        updateScheduleType(type, false);
        setupForKnownSchedule(getView());
    }

    private void updateScheduleType(int type, boolean createNewSchedule) {

        Log.d(TAG, "updateScheduleType :" + type);

        if (createNewSchedule || schedule == null) {
            Log.d(TAG, "Creating new schedule");
            schedule = new Schedule();
        }

        switch (type) {
        case Schedule.SCHEDULE_TYPE_HOURLY:
            if (timesPerDay > 0) {
                schedule.rule().setInterval(24 / timesPerDay);
            }
            schedule.setDose(doses[0]);
            schedule.setType(Schedule.SCHEDULE_TYPE_HOURLY);
            break;
        case Schedule.SCHEDULE_TYPE_CYCLE:
            schedule.setType(Schedule.SCHEDULE_TYPE_CYCLE);
            break;
        case Schedule.SCHEDULE_TYPE_SOMEDAYS:
            schedule.setType(Schedule.SCHEDULE_TYPE_SOMEDAYS);
            break;
        default:
            schedule.setType(Schedule.SCHEDULE_TYPE_EVERYDAY);
            break;
        }

        Log.d(TAG, "Set schedule type: " + schedule.type());

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_schedule_import, container, false);
        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);
        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);
        boxScheduleChangedMsg = rootView.findViewById(R.id.schedule_changed_msg);
        changeList = (LinearLayout) rootView.findViewById(R.id.schedule_changes_list);
        newScheduleBox = rootView.findViewById(R.id.schedule_new_indicator);

        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);

        continueButton = (Button) rootView.findViewById(R.id.button3);

        continueButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((ConfirmSchedulesActivity) getActivity()).next();
            }
        });

        updateScheduleType(schedule != null ? schedule.type() : Schedule.SCHEDULE_TYPE_EVERYDAY, false);
        setupScheduleSpinner();
        setupDaySelectionListeners(rootView);
        setupHourlyRepetitionLinsteners();
        setupStartEndDatePickers(rootView);
        setupCycleSpinner();
        setupForKnownSchedule(rootView);

        changes = changes(schedule, prescriptionWrapper);
        setupChanges(changes);

        setupNewMessage();

        updateColors(rootView);

        return rootView;
    }

    private void updateColors(View rootView) {

        int color = DB.patients().getActive(getActivity()).color();

        ((TextView) rootView.findViewById(R.id.textView3)).setTextColor(color);
        ((TextView) rootView.findViewById(R.id.textView2)).setTextColor(color);
        (rootView.findViewById(R.id.imageView)).setBackgroundColor(color);
        (rootView.findViewById(R.id.imageView1)).setBackgroundColor(color);

        hourlyIntervalEditText.setTextColor(color);
        hourlyIntervalFrom.setTextColor(color);
        hourlyIntervalRepeatDose.setTextColor(color);
        buttonScheduleStart.setTextColor(color);
        buttonScheduleEnd.setTextColor(color);
        periodValue.setTextColor(color);
        periodRest.setTextColor(color);
    }

    private void setupNewMessage() {

        ImageView icon = (ImageView) newScheduleBox.findViewById(R.id.new_schedule_icon);
        TextView text = (TextView) newScheduleBox.findViewById(R.id.new_schedule_text);

        if (isNew) {
            icon.setImageResource(R.drawable.ic_done_black_48dp);
            text.setText(getString(R.string.scan_new_schedule));
        } else {
            icon.setImageResource(R.drawable.ic_edit_black_48dp);
            text.setText(getString(R.string.scan_existing_schedule));
        }

    }

    private void setupChanges(List<String> changes) {
        if (!changes.isEmpty()) {
            boxScheduleChangedMsg.setVisibility(View.VISIBLE);
            LayoutInflater li = getActivity().getLayoutInflater();
            for (String c : changes) {

                View item = li.inflate(R.layout.schedule_change_list_item, null);
                ((TextView) item).setText(c);
                changeList.addView(item);
            }

        } else {
            boxScheduleChangedMsg.setVisibility(View.GONE);
        }

    }

    private void setupCycleSpinner() {
        final String[] cycles = getResources().getStringArray(R.array.schedule_cycles);

        cycleSpinnerTrigger.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
                b.setTitle(R.string.schedule_type_common_periods);
                b.setItems(cycles, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        String c = cycles[which];
                        String[] parts = c.replaceAll(" ", "").split("\\+");
                        periodValue.setText(parts[0]);
                        periodRest.setText(parts[1]);
                        schedule.setCycle(Integer.valueOf(parts[0]), Integer.valueOf(parts[1]));
                    }
                });

                AlertDialog d = b.create();
                d.show();
            }
        });
    }

    private void updateHourlyIntervalBox() {
        LocalTime t = schedule.startTime();
        if (t == null) {
            t = LocalTime.now().withMinuteOfHour(0);
            schedule.setStartTime(t);
        }
        String time = new LocalTime(t.getHourOfDay(), t.getMinuteOfHour()).toString("kk:mm");
        hourlyIntervalFrom.setText(getString(R.string.first_intake) + ": " + time);

        if (schedule.rule().interval() < 1) {
            schedule.rule().setInterval(8);
        }
        schedule.rule().setFrequency(Frequency.HOURLY);
        hourlyIntervalEditText.setText(String.valueOf(schedule.rule().interval()));
        hourlyIntervalRepeatDose.setText(schedule.displayDose());
    }

    private void setupForKnownSchedule(View rootView) {

        Log.d(TAG, "Setup for known schedule: id = " + schedule.getId());

        int type = ScheduleTypeFragment.TYPE_ROUTINES;

        if (schedule.type() == Schedule.SCHEDULE_TYPE_HOURLY) {
            type = ScheduleTypeFragment.TYPE_HOURLY;
        } else if (schedule.type() == Schedule.SCHEDULE_TYPE_CYCLE) {
            type = ScheduleTypeFragment.TYPE_PERIOD;
        }

        Log.d(TAG, "Setup for known schedule:  " + type);

        boxTimesByDay.setVisibility(View.GONE);
        boxTimetable.setVisibility(View.GONE);
        boxRepeat.setVisibility(View.GONE);
        boxHourlyInterval.setVisibility(View.GONE);
        boxPeriod.setVisibility(View.GONE);
        boxDuration.setVisibility(View.VISIBLE);

        if (type == ScheduleTypeFragment.TYPE_ROUTINES) {
            boxTimesByDay.setVisibility(View.VISIBLE);
            boxTimetable.setVisibility(View.VISIBLE);
            boxRepeat.setVisibility(View.VISIBLE);
            scheduleSpinner.setSelection(selectedScheduleIdx);
            checkSelectedDays(rootView, schedule.days());
            setupRepetitions(rootView);
            updateRepeatTypeAndInterval(rootView);
        } else if (type == ScheduleTypeFragment.TYPE_HOURLY) {
            schedule.rule().setDays(Schedule.noWeekDays());
            boxHourlyInterval.setVisibility(View.VISIBLE);
            updateHourlyIntervalBox();
        } else {
            boxTimesByDay.setVisibility(View.VISIBLE);
            boxTimetable.setVisibility(View.VISIBLE);
            boxPeriod.setVisibility(View.VISIBLE);
            updatePeriodSelector();
        }

    }

    private void updatePeriodSelector() {
        periodValue.setText(String.valueOf(schedule.getCycleDays()));
        periodRest.setText(String.valueOf(schedule.getCycleRest()));

        periodValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NumberPickerBuilder npb = new NumberPickerBuilder().setDecimalVisibility(NumberPicker.INVISIBLE)
                        .setMinNumber(1).setMaxNumber(100).setPlusMinusVisibility(NumberPicker.INVISIBLE)
                        .setFragmentManager(getChildFragmentManager())
                        .setTargetFragment(ScheduleImportFragment.this).setReference(REF_DIALOG_CYCLE_DAYS)
                        .setStyleResId(R.style.BetterPickersDialogFragment_Calendula);
                npb.show();
            }
        });

        periodRest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                NumberPickerBuilder npb = new NumberPickerBuilder().setDecimalVisibility(NumberPicker.INVISIBLE)
                        .setMinNumber(1).setMaxNumber(100).setPlusMinusVisibility(NumberPicker.INVISIBLE)
                        .setFragmentManager(getChildFragmentManager())
                        .setTargetFragment(ScheduleImportFragment.this).setReference(REF_DIALOG_CYCLE_REST)
                        .setStyleResId(R.style.BetterPickersDialogFragment_Calendula);
                npb.show();
            }
        });
    }

    private void updateRepeatTypeAndInterval(View rootView) {
        int repeatType = schedule.type();
        setRepeatType(repeatType, rootView, true);
        repeatTypeSpinner.setSelection(repeatType);
        intervalEditText.setText(String.valueOf(schedule.rule().interval()));
    }

    private void setupHourlyRepetitionLinsteners() {
        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();

                RadialTimePickerDialog timePickerDialog = RadialTimePickerDialog.newInstance(
                        ScheduleImportFragment.this, time.getHourOfDay(), time.getMinuteOfHour(), true);
                timePickerDialog.show(getChildFragmentManager(), "111");
            }
        });

        hourlyIntervalRepeatDose.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showHourlyDosePickerDialog();
            }
        });
    }

    private void setupRepetitions(final View rooView) {
        ruleText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showRecurrencePickerDialog();
            }
        });

        repeatTypeSpinner
                .setAdapter(new ArrayAdapter<>(getActivity(), R.layout.support_simple_spinner_dropdown_item,
                        getResources().getStringArray(R.array.schedule_repeat_types)));
        repeatTypeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                setRepeatType(position, rooView, !ignoreNextEvent);
                ignoreNextEvent = false;
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
            }
        });

        freqSpinner.setAdapter(new ArrayAdapter<>(getActivity(), R.layout.support_simple_spinner_dropdown_item,
                getResources().getStringArray(R.array.schedule_repeat_frequency_units)));
        freqSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                setFrequency(position, rooView);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        intervalEditText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showIntervalPickerDIalog();
            }
        });
    }

    private void setupStartEndDatePickers(View rootView) {

        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(getActivity(),
                        new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                                Log.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(getActivity(),
                        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("Do you want this schedule to 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());

        if (schedule.end() == null && isNew && hasEnd && daysToEnd > 0) {
            LocalDate end = schedule.start().plusDays(daysToEnd);
            setScheduleEnd(end);
        } else {
            setScheduleEnd(schedule.end());
        }
    }

    private void setFrequency(int freq, View rootView) {
        int type = ScheduleTypeFragment.TYPE_ROUTINES; // TODO ScheduleHelper.instance().getScheduleType();
        if (type == ScheduleTypeFragment.TYPE_ROUTINES) {
            Frequency frequency = FREQ[freq];
            schedule.rule().setFrequency(frequency);

            if (frequency == Frequency.WEEKLY) {
                int dayCount = schedule.dayCount();
                if (dayCount == 0 || dayCount == 7) {
                    checkToday(rootView);
                }
                daySelectionBox.setVisibility(View.VISIBLE);
            } else {
                schedule.rule().setDays(null);
                daySelectionBox.setVisibility(View.GONE);
            }
        }
    }

    private void setRepeatType(int type, View v, boolean updateUi) {
        int sType = ScheduleTypeFragment.TYPE_ROUTINES;
        if (sType == ScheduleTypeFragment.TYPE_ROUTINES) {
            schedule.setType(type);

            if (updateUi) {
                //resetRule();
                if (type == Schedule.SCHEDULE_TYPE_EVERYDAY) {
                    daySelectionBox.setVisibility(View.VISIBLE);
                    customRepeatBox.setVisibility(View.GONE);
                    ruleText.setVisibility(View.GONE);

                    schedule.rule().setInterval(0);
                    schedule.rule().setFrequency(Frequency.DAILY);

                    checkAllDays(v);

                } else if (type == Schedule.SCHEDULE_TYPE_SOMEDAYS) {
                    daySelectionBox.setVisibility(View.VISIBLE);
                    customRepeatBox.setVisibility(View.GONE);
                    ruleText.setVisibility(View.GONE);

                    // Interval
                    schedule.rule().setInterval(0);
                    // frequency
                    schedule.rule().setFrequency(Frequency.DAILY);
                    // byday
                    if (schedule.dayCount() == 7 || schedule.dayCount() == 0) {
                        checkToday(v);
                    } else {
                        checkSelectedDays(v, schedule.days());
                    }

                } else if (type == Schedule.SCHEDULE_TYPE_INTERVAL) {
                    ruleText.setVisibility(View.GONE);
                    customRepeatBox.setVisibility(View.VISIBLE);

                    int interval = schedule.rule().interval();
                    if (interval < 2) {
                        interval = 2;
                    }
                    schedule.rule().setInterval(interval);
                    intervalEditText.setText(String.valueOf(schedule.rule().interval()));

                    Frequency f = schedule.rule().frequency();

                    if (f.equals(Frequency.WEEKLY)) {
                        freqSpinner.setSelection(1);
                        setFrequency(1, v);
                    } else if (f.equals(Frequency.MONTHLY)) {
                        freqSpinner.setSelection(2);
                        setFrequency(2, v);
                    } else {
                        freqSpinner.setSelection(0);
                        setFrequency(0, v);
                    }
                }
            }
        }
    }

    private Spanned getCurrentSchedule() {

        String text = getString(R.string.schedule_custom_rule_text, schedule.toReadableString(getActivity()));
        int count = schedule.rule().iCalRule().getCount();
        if (count > 0) {
            text += "<br><u>" + getString(R.string.schedules_stop_after, count) + "</u>";
        }
        return Html.fromHtml(text);
    }

    private void checkAllDays(View v) {
        checkSelectedDays(v, Schedule.allWeekDays());
    }

    private void checkToday(View v) {
        boolean[] days = Schedule.noWeekDays();
        days[LocalDate.now().getDayOfWeek() - 1] = true;
        checkSelectedDays(v, days);
    }

    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        if (schedule.type() != Schedule.SCHEDULE_TYPE_HOURLY) {
            if (isNew)
                scheduleSpinner.setSelection(timesPerDay > 0 ? timesPerDay - 1 : 0);
            else
                scheduleSpinner.setSelection(schedule.items().size() - 1);
            //checkSelectedDays(view, schedule!=null ? schedule.days() : Schedule.allWeekDays());
        }
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    private void setupScheduleSpinner() {
        // Create an ArrayAdapter using the string array and a default spinner layout
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getActivity(), R.array.schedules_array,
                R.layout.spinner_text_item);
        // Specify the layout to use when the list of choices appears
        adapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        // Apply the adapter to the spinner
        scheduleSpinner.setAdapter(adapter);
        scheduleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                String selected = (String) adapterView.getItemAtPosition(i);
                onScheduleSelected(selected, i);
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });
    }

    void onScheduleSelected(String selection, int index) {

        selectedScheduleIdx = index;
        String schedules[] = getResources().getStringArray(R.array.schedules_array);

        timesPerDay = 0;
        // obtain times per day from selected schedule
        for (int i = 0; i < schedules.length; i++) {
            if (schedules[i].equalsIgnoreCase(selection)) {
                timesPerDay = i + 1;
                break;
            }
        }
        addTimetableEntries(timesPerDay, DB.routines().findAllForActivePatient(getActivity()));
    }

    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];

                if (!daySelected) {
                    ((TextView) view).setTextAppearance(getActivity(), R.style.schedule_day_unselected);
                    view.setBackgroundResource(R.drawable.dayselector_circle_unselected);
                } else {
                    ((TextView) view).setTextAppearance(getActivity(), R.style.schedule_day_selected);
                    view.setBackgroundResource(R.drawable.dayselector_circle);
                }

                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);
                }

                Log.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(1).setMaxNumber(31).setPlusMinusVisibility(NumberPicker.INVISIBLE)
                .setFragmentManager(getChildFragmentManager()).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 String[] types = { "2", "3", "4", "6", "8", "12" };
        b.setItems(types, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                int result = Integer.valueOf(types[which]);
                hourlyIntervalEditText.setText("" + result);
                schedule.rule().setFrequency(Frequency.HOURLY);
                schedule.rule().setInterval(result);
            }
        });

        b.show();
    }

    void showRecurrencePickerDialog() {
        RecurrencePickerDialog dialog = new RecurrencePickerDialog();

        DateTime start = schedule.start() != null ? schedule.start().toDateTimeAtStartOfDay()
                : DateTime.now().withTimeAtStartOfDay();

        Bundle b = new Bundle();

        b.putString(RecurrencePickerDialog.BUNDLE_RRULE, schedule.rule().toIcal().replace("RRULE:", ""));
        b.putLong(RecurrencePickerDialog.BUNDLE_START_TIME_MILLIS, DateTime.now().getMillis());
        //b.putString(RecurrencePickerDialog.BUNDLE_TIME_ZONE, t.timezone);

        dialog.setArguments(b);
        dialog.setOnRecurrenceSetListener(this);
        dialog.show(getChildFragmentManager(), "REC");
    }

    void addTimetableEntries(int timesPerDay, List<Routine> routines) {

        Collections.sort(sItems, 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<ScheduleItem>();

        boolean enableDelete = timesPerDay > 1;

        for (int i = 0; i < timesPerDay; i++) {
            // try to get previous routine from state holder
            ScheduleItem s;

            if (i < sItems.size()) {
                ScheduleItem toCopy = sItems.get(i);
                s = new ScheduleItem(null, toCopy.routine(), toCopy.dose());
            } else {

                float dose = doses.length > 0 ? doses[0] : 1;
                Log.d(TAG, "Creating new scheduleItem with dose " + dose + ", " + Arrays.toString(doses));
                s = new ScheduleItem(null, (i < routines.size()) ? routines.get(i) : null, dose);
            }

            if (s != null) {
                scheduleItems.add(s);
            }

            View view = buildTimetableEntry(s, routineNames, enableDelete);
            timetableContainer.addView(view, params);
        }

        sItems = scheduleItems;
    }

    String[] getUpdatedRoutineNames() {

        List<Routine> routines = DB.routines().findAllForActivePatient(getActivity());

        int j = 0;
        String[] routineNames = new String[routines.size() + 1];
        for (Routine r : routines) {
            routineNames[j++] = r.name();
        }

        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.routine(), entry);
        setupScheduleEntrySpinners(entry, r, routineNames);

        if (enableDelete) {
            entry.findViewById(R.id.entry_remove).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    sItems.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<String>(getActivity(),
                android.R.layout.simple_spinner_item, routineNames);
        routineAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        routineSpinner.setAdapter(routineAdapter);
    }

    private void setupScheduleEntrySpinners(final View entryView, ScheduleItem scheduleItem,
            String[] routineNames) {

        final Spinner routineSpinner = (Spinner) entryView.findViewById(R.id.entry_routine_spinner);
        final TextView doseTv = (TextView) entryView.findViewById(R.id.entry_dose_textview);
        //        final Spinner doseSpinner = (Spinner) entryView.findViewById(R.id.entry_dose_spinner);

        doseTv.setTag(scheduleItem);
        routineSpinner.setTag(scheduleItem);

        // set up the routine selection adapter
        updateRoutineSelectionAdapter(entryView, routineSpinner, routineNames);

        if (scheduleItem != null && scheduleItem.routine() != null) {
            String routineName = scheduleItem.routine().name();
            int index = Arrays.asList(routineNames).indexOf(routineName);
            routineSpinner.setSelection(index);
        } else {
            routineSpinner.setSelection(routineNames.length - 1);
        }

        doseTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showDosePickerDialog((ScheduleItem) v.getTag(), (TextView) v);
            }
        });

        doseTv.setText(scheduleItem.displayDose());

        // setup listeners
        routineSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                String selected = (String) adapterView.getItemAtPosition(i);
                Routine r = Routine.findByName(selected);
                ScheduleItem item = ((ScheduleItem) routineSpinner.getTag());

                if (r != null) {
                    updateEntryTime(r, entryView);
                } else {
                    updateEntryTime(null, entryView);
                    showAddNewRoutineDialog(entryView);
                }
                Log.d(TAG, "Updated routine to " + (r != null ? r.name() : "NULL") + " on item " + item.getId());
                item.setRoutine(r);

                logScheduleItems();
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
            }
        });

        routineSpinner.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_UP) {

                    if (((String) routineSpinner.getSelectedItem())
                            .equalsIgnoreCase(getString(R.string.create_new_routine))) {
                        showAddNewRoutineDialog(entryView);
                        return true;
                    }
                }
                return false;
            }
        });
    }

    private void logScheduleItems() {
        for (ScheduleItem si : sItems) {
            Log.d("TAG", (si.routine() != null ? si.routine().name() : "NONE") + ", " + si.dose()
                    + " ****************************");
        }
    }

    void updateEntryTime(Routine r, View entry) {
        String hourText;
        String minuteText;
        if (r != null) {
            hourText = (r.time().getHourOfDay() < 10 ? "0" + r.time().getHourOfDay() : r.time().getHourOfDay())
                    + ":";
            minuteText = (r.time().getMinuteOfHour() < 10 ? "0" + r.time().getMinuteOfHour()
                    : r.time().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);
                String names[] = getUpdatedRoutineNames();
                updateRoutineSelectionAdapter(entryView, rSpinner, names);

                Log.d(TAG, "Routine name: " + r.name());
                Log.d(TAG, "Routine time: " + r.time().toString("hh:mm"));
                Log.d(TAG, "Names: " + Arrays.toString(names));

                int selection = Arrays.asList(names).indexOf(r.name());
                rSpinner.setSelection(selection);

                updateEntryTime(r, entryView);
                addRoutineFragment.dismiss();
            }
        });

        addRoutineFragment.show(fm, "fragment_edit_name");
    }

    private DosePickerFragment getDosePickerFragment(Presentation p, ScheduleItem item, Schedule s) {
        DosePickerFragment dpf = null;
        Bundle arguments = new Bundle();

        if (p != null && (p.equals(Presentation.DROPS) || p.equals(Presentation.PILLS)
                || p.equals(Presentation.CAPSULES) || p.equals(Presentation.EFFERVESCENT))) {
            dpf = new PillDosePickerFragment();
        } else {
            dpf = new DefaultDosePickerFragment();
            arguments.putSerializable("presentation", p);
        }
        if (item != null) {
            arguments.putDouble("dose", item.dose());
        } else if (s != null) {
            arguments.putDouble("dose", s.dose());
        }

        dpf.setArguments(arguments);
        return dpf;

    }

    void showDosePickerDialog(final ScheduleItem item, final TextView tv) {

        Presentation p;

        if (prescriptionWrapper.isGroup) {
            HomogeneousGroup g = DB.groups().findOneBy(HomogeneousGroup.COLUMN_GROUP,
                    prescriptionWrapper.group.group);
            p = Presentation.expected(g.name, g.name);
        } else {
            p = Prescription.findByCn(prescriptionWrapper.prescription.cn).expectedPresentation();
        }

        final DosePickerFragment dpf = getDosePickerFragment(p, item, null);

        if (dpf != null) {
            FragmentManager fm = getActivity().getSupportFragmentManager();
            dpf.setOnDoseSelectedListener(new LiquidDosePickerFragment.OnDoseSelectedListener() {
                @Override
                public void onDoseSelected(double dose) {
                    Log.d(TAG, "Set dose " + dose + " to item " + item.routine().name() + ", " + item.getId());
                    item.setDose((float) dose);
                    tv.setText(item.displayDose());

                    logScheduleItems();
                }
            });
            dpf.show(fm, "fragment_select_dose");
        } else {

        }

    }

    void showHourlyDosePickerDialog() {

        Presentation p;

        if (prescriptionWrapper.isGroup) {
            p = Presentation.expected(prescriptionWrapper.group.name, prescriptionWrapper.group.name);
        } else {
            p = Prescription.findByCn(prescriptionWrapper.prescription.cn).expectedPresentation();
        }

        final DosePickerFragment dpf = getDosePickerFragment(p, null, schedule);

        if (dpf != null) {
            FragmentManager fm = getActivity().getSupportFragmentManager();
            dpf.setOnDoseSelectedListener(new LiquidDosePickerFragment.OnDoseSelectedListener() {
                @Override
                public void onDoseSelected(double dose) {
                    schedule.setDose((float) dose);
                    hourlyIntervalRepeatDose.setText(schedule.displayDose());
                }
            });
            dpf.show(fm, "fragment_select_dose");
        } else {

        }
    }

    void checkSelectedDays(View rootView, boolean[] days) {

        Log.d(TAG, "Checking selected days: " + Arrays.toString(days));
        schedule.setDays(days);

        TextView mo = ((TextView) rootView.findViewById(R.id.day_mo));
        TextView tu = ((TextView) rootView.findViewById(R.id.day_tu));
        TextView we = ((TextView) rootView.findViewById(R.id.day_we));
        TextView th = ((TextView) rootView.findViewById(R.id.day_th));
        TextView fr = ((TextView) rootView.findViewById(R.id.day_fr));
        TextView sa = ((TextView) rootView.findViewById(R.id.day_sa));
        TextView su = ((TextView) rootView.findViewById(R.id.day_su));

        TextView[] daysTvs = new TextView[] { mo, tu, we, th, fr, sa, su };

        for (int i = 0; i < daysTvs.length; i++) {
            boolean isSelected = days[i];

            StateListDrawable sld = (StateListDrawable) daysTvs[i].getBackground();
            GradientDrawable shape = (GradientDrawable) sld.getCurrent();
            shape.setColor(isSelected ? color : Color.WHITE);

            daysTvs[i].setTextColor(isSelected ? Color.WHITE : color);
            daysTvs[i].setTypeface(null, isSelected ? Typeface.BOLD : Typeface.NORMAL);

        }
    }

    @Override
    public void onDialogNumberSet(int reference, int number, double decimal, boolean isNegative,
            double fullNumber) {

        if (reference == REF_DIALOG_ROUTINE_INTERVAL) {
            intervalEditText.setText("" + number);
            schedule.rule().setInterval(number);
        } else if (reference == REF_DIALOG_HOURLY_INTERVAL) {
            hourlyIntervalEditText.setText("" + number);
            schedule.rule().setFrequency(Frequency.HOURLY);
            schedule.rule().setInterval(number);
        } else if (reference == REF_DIALOG_CYCLE_DAYS) {
            periodValue.setText(String.valueOf(number));
            cycleDays = number;
            if (cycleRest > 0) {
                schedule.setCycle(cycleDays, cycleRest);
            }
        } else if (reference == REF_DIALOG_CYCLE_REST) {
            periodRest.setText(String.valueOf(number));
            cycleRest = number;
            if (cycleDays > 0) {
                schedule.setCycle(cycleDays, cycleRest);
            }
        }
    }

    @Override
    public void onTimeSet(RadialTimePickerDialog radialTimePickerDialog, int hour, int minute) {

        String time = new LocalTime(hour, minute).toString("kk:mm");
        hourlyIntervalFrom.setText(getString(R.string.first_intake) + ": " + time);
        schedule.setStartTime(new LocalTime(hour, minute));
    }

    @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);

        Log.d(TAG, "OnRecurrenceSet: " + event.startDate);

        schedule.setRepetition(new RepetitionRule("RRULE:" + s));
        setScheduleStart(schedule.start());
        LocalDate end = schedule.end();
        Log.d(TAG, "ICAL: " + schedule.rule().toIcal());
        setScheduleEnd(end);
        Log.d(TAG, "ICAL: " + schedule.rule().toIcal());
        ruleText.setText(getCurrentSchedule());
    }

    void setScheduleStart(LocalDate start) {
        schedule.setStart(start);
        if (start == null) {
            buttonScheduleStart.setText(getString(R.string.button_schedule_repeat_today));
            clearStartButton.setVisibility(View.INVISIBLE);
        } else {
            buttonScheduleStart.setText(start.toString(getString(R.string.schedule_limits_date_format)));
            clearStartButton.setVisibility(View.VISIBLE);
        }
    }

    void setScheduleEnd(LocalDate end) {
        if (end == null) {
            buttonScheduleEnd.setText(getString(R.string.never));
            schedule.rule().iCalRule().setUntil(null);
            clearEndButton.setVisibility(View.INVISIBLE);
        } else {
            DateValue v = new DateTimeValueImpl(end.getYear(), end.getMonthOfYear(), end.getDayOfMonth(), 0, 0, 0);
            schedule.rule().iCalRule().setUntil(v);
            buttonScheduleEnd.setText(end.toString(getString(R.string.schedule_limits_date_format)));
            clearEndButton.setVisibility(View.VISIBLE);
        }
    }

    public boolean validate() {

        // check dose as in prescriptions
        return true;
    }

    public Schedule getSchedule() {
        return schedule;
    }

    public List<ScheduleItem> getScheduleItems() {
        return sItems;
    }

    public PrescriptionWrapper getPrescriptionWrapper() {
        return prescriptionWrapper;
    }

    public Schedule findByPrescriptionWrapper(PrescriptionWrapper pw) {
        if (pw.cn != null) {
            Log.d("FindByPW", "Prescription: " + pw.cn);
            Medicine m = DB.medicines().findOneBy(Medicine.COLUMN_CN, pw.cn);
            if (m != null) {
                return DB.schedules().findScannedByMedicine(m);
            }
        } else if (pw.isGroup) {
            Log.d("FindByPW", "Group: " + pw.group.getId());
            Medicine m = DB.medicines().findOneBy(Medicine.COLUMN_HG, pw.group.getId());
            if (m != null) {
                return DB.schedules().findScannedByMedicine(m);
            }
        }
        return null;
    }

    public List<String> changes(Schedule s, PrescriptionWrapper pw) {

        List<String> changes = new ArrayList<>();

        int interval = pw.s.p;

        if (pw.s.d == 0.0) { // || pw.s.d >= 2.0
            // dose is zero
            Log.d(TAG, "Item dose is ambiguous");
            changes.add(" " + getString(R.string.scan_dose_zero_msg));
        }

        if (s != null && !isNew && !s.repeatsHourly()) {
            List<ScheduleItem> items = s.items();
            for (ScheduleItem i : items) {
                if (i.dose() != pw.s.d && pw.s.d > 0) {
                    // dose is different
                    Log.d(TAG, "Item dose is different [" + i.dose() + ", " + pw.s.d + ", " + items.size() + "]");
                    changes.add(" " + getString(R.string.scan_dose_changed_msg));
                    break;
                }
            }
            if (interval > 0) {
                int times = 24 / interval;
                if (times != items.size()) {
                    // times by day is different
                    Log.d(TAG, "Times by day is different[" + times + ", " + items.size() + "]");
                    changes.add(" " + getString(R.string.scan_frequency_changed_msg, items.size(), times));
                }
            }
        } else if (s != null && !isNew) {
            if (s.dose() != pw.s.d && pw.s.d > 0) {
                // dose is different
                changes.add(" " + getString(R.string.scan_dose_changed_msg));
                Log.d(TAG, "Dose is different [" + s.dose() + ", " + pw.s.d + "]");
            }
            if (s.rule().interval() != interval) {
                changes.add(" " + getString(R.string.scan_interval_changed_msg, s.rule().interval(), interval));
                Log.d(TAG, "Interval is different[" + interval + ", " + s.rule().interval() + "]");
            }
        }

        if (hasEnd) {
            changes.add(" " + getString(R.string.scan_schedule_ends_msg, daysToEnd));
        }

        return changes;
    }

    public boolean isNew() {
        return isNew;
    }

    public void setNew(boolean isNew) {
        this.isNew = isNew;
    }
}