es.usc.citius.servando.calendula.activities.ScheduleCreationActivity.java Source code

Java tutorial

Introduction

Here is the source code for es.usc.citius.servando.calendula.activities.ScheduleCreationActivity.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.activities;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.astuetz.PagerSlidingTabStrip;
import com.j256.ormlite.misc.TransactionManager;
import com.nispok.snackbar.Snackbar;
import com.nispok.snackbar.SnackbarManager;
import com.nispok.snackbar.enums.SnackbarType;

import org.joda.time.DateTime;
import org.joda.time.LocalTime;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import es.usc.citius.servando.calendula.CalendulaActivity;
import es.usc.citius.servando.calendula.CalendulaApp;
import es.usc.citius.servando.calendula.R;
import es.usc.citius.servando.calendula.database.DB;
import es.usc.citius.servando.calendula.events.PersistenceEvents;
import es.usc.citius.servando.calendula.fragments.ScheduleSummaryFragment;
import es.usc.citius.servando.calendula.fragments.ScheduleTimetableFragment;
import es.usc.citius.servando.calendula.fragments.SelectMedicineListFragment;
import es.usc.citius.servando.calendula.persistence.DailyScheduleItem;
import es.usc.citius.servando.calendula.persistence.Medicine;
import es.usc.citius.servando.calendula.persistence.Patient;
import es.usc.citius.servando.calendula.persistence.Schedule;
import es.usc.citius.servando.calendula.persistence.ScheduleItem;
import es.usc.citius.servando.calendula.scheduling.AlarmScheduler;
import es.usc.citius.servando.calendula.scheduling.DailyAgenda;
import es.usc.citius.servando.calendula.util.FragmentUtils;
import es.usc.citius.servando.calendula.util.ScheduleHelper;
import es.usc.citius.servando.calendula.util.ScreenUtils;
import es.usc.citius.servando.calendula.util.Snack;

//import es.usc.citius.servando.calendula.fragments.MedicineCreateOrEditFragment;

public class ScheduleCreationActivity extends CalendulaActivity implements ViewPager.OnPageChangeListener {

    public static final String TAG = ScheduleCreationActivity.class.getName();
    /**
     * The {@link android.support.v4.view.PagerAdapter} that will provide
     * fragments for each of the sections. We use a
     * {@link FragmentPagerAdapter} derivative, which will keep every
     * loaded fragment in memory. If this becomes too memory intensive, it
     * may be best to switch to a
     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
     */
    SectionsPagerAdapter mSectionsPagerAdapter;

    Schedule mSchedule;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    ViewPager mViewPager;
    long mScheduleId;
    PagerSlidingTabStrip tabs;
    MenuItem removeItem;
    Toolbar toolbar;

    boolean autoStepDone = false;
    int pColor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_schedules);

        pColor = DB.patients().getActive(this).color();
        setupToolbar(null, pColor);
        setupStatusBar(pColor);
        subscribeToEvents();
        processIntent();

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        TextView title = ((TextView) findViewById(R.id.textView2));
        title.setBackgroundColor(pColor);
        title.setText(getString(mScheduleId != -1 ? R.string.title_edit_schedule_activity
                : R.string.title_create_schedule_activity));

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        mViewPager.setOnPageChangeListener(this);
        mViewPager.setOffscreenPageLimit(3);
        tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);

        tabs.setOnPageChangeListener(this);
        tabs.setAllCaps(true);
        tabs.setShouldExpand(true);
        tabs.setDividerPadding(3);
        tabs.setDividerColor(getResources().getColor(R.color.white_50));
        tabs.setDividerColor(getResources().getColor(R.color.transparent));
        tabs.setIndicatorHeight(ScreenUtils.dpToPx(getResources(), 4));
        tabs.setIndicatorColor(ScreenUtils.equivalentNoAlpha(pColor, 0.8f));
        tabs.setTextColor(Color.parseColor("#222222"));
        tabs.setUnderlineColor(ScreenUtils.equivalentNoAlpha(pColor, 0.5f));
        tabs.setViewPager(mViewPager);

        if (mSchedule != null) {
            mViewPager.setCurrentItem(1);
        }

        findViewById(R.id.add_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                saveSchedule();
            }
        });

    }

    private void processIntent() {
        mScheduleId = getIntent().getLongExtra(CalendulaApp.INTENT_EXTRA_SCHEDULE_ID, -1);
        int scheduleType = getIntent().getIntExtra("scheduleType", -1);
        if (mScheduleId != -1) {
            Schedule s = Schedule.findById(mScheduleId);
            if (s != null) {
                ScheduleHelper.instance().setSelectedMed(s.medicine());
                ScheduleHelper.instance().setTimesPerDay(s.items().size());
                ScheduleHelper.instance().setSelectedScheduleIdx(s.items().size() - 1);
                ScheduleHelper.instance().setScheduleItems(s.items());
                ScheduleHelper.instance().setSchedule(s);
                mSchedule = s;
            } else {
                Snack.show("Schedule not found :(", this);
            }
        } else if (scheduleType != -1) {
            ScheduleHelper.instance().setScheduleType(scheduleType);
        }
    }

    public void createSchedule() {
        try {

            final Schedule s = ScheduleHelper.instance().getSchedule();

            TransactionManager.callInTransaction(DB.helper().getConnectionSource(), new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    // save schedule
                    final Patient patient = DB.patients().getActive(getBaseContext());
                    s.setMedicine(ScheduleHelper.instance().getSelectedMed());
                    s.setPatient(patient);
                    s.save();

                    Log.d(TAG, "Saving schedule..." + s.toString());

                    if (!s.repeatsHourly()) {
                        for (ScheduleItem item : ScheduleHelper.instance().getScheduleItems()) {
                            item.setSchedule(s);
                            item.save();
                            Log.d(TAG, "Saving item..." + item.getId());
                            // add to daily schedule
                            DailyAgenda.instance().addItem(patient, item, false);
                        }
                    } else {
                        for (DateTime time : s.hourlyItemsToday()) {
                            LocalTime timeToday = time.toLocalTime();
                            DailyAgenda.instance().addItem(patient, s, timeToday);
                        }
                    }
                    // save and fire event
                    DB.schedules().saveAndFireEvent(s);
                    return null;
                }
            });

            ScheduleHelper.instance().clear();
            AlarmScheduler.instance().onCreateOrUpdateSchedule(s, ScheduleCreationActivity.this);
            Log.d(TAG, "Schedule saved successfully!");
            Snack.show(R.string.schedule_created_message, this);
            CalendulaApp.eventBus().post(PersistenceEvents.SCHEDULE_EVENT);
            finish();
        } catch (Exception e) {
            Snack.show("Error creating schedule", this);
            e.printStackTrace();
        }
    }

    public void updateSchedule() {
        try {
            final Schedule s = mSchedule;

            TransactionManager.callInTransaction(DB.helper().getConnectionSource(), new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    // save schedule

                    s.setMedicine(ScheduleHelper.instance().getSelectedMed());
                    final Patient patient = s.patient();

                    List<Long> routinesTaken = new ArrayList<Long>();

                    if (!s.repeatsHourly()) {
                        // remove days if changed
                        boolean[] days = s.days();
                        for (DailyScheduleItem dsi : DB.dailyScheduleItems().findBySchedule(s)) {
                            if (days[dsi.date().getDayOfWeek() - 1]) {
                                DB.dailyScheduleItems().remove(dsi);
                            }
                        }

                        for (ScheduleItem item : s.items()) {
                            DailyScheduleItem d = DailyScheduleItem.findByScheduleItem(item);
                            // if taken today, add to the list
                            if (d != null && d.takenToday()) {
                                routinesTaken.add(item.routine().getId());
                            }
                            item.deleteCascade();
                        }

                        // save new items
                        for (ScheduleItem i : ScheduleHelper.instance().getScheduleItems()) {

                            ScheduleItem item = new ScheduleItem();
                            item.setDose(i.dose());
                            item.setRoutine(i.routine());
                            item.setSchedule(s);
                            item.save();
                            // add to daily schedule
                            DailyAgenda.instance().addItem(patient, item,
                                    routinesTaken.contains(item.routine().getId()));
                        }
                    } else {
                        DB.dailyScheduleItems().removeAllFrom(s);
                        for (DateTime time : s.hourlyItemsToday()) {
                            LocalTime timeToday = time.toLocalTime();
                            DailyAgenda.instance().addItem(patient, s, timeToday);
                        }
                    }

                    // save and fire event
                    DB.schedules().saveAndFireEvent(s);
                    return null;
                }
            });

            ScheduleHelper.instance().clear();
            AlarmScheduler.instance().onCreateOrUpdateSchedule(s, ScheduleCreationActivity.this);
            Log.d(TAG, "Schedule saved successfully!");
            Toast.makeText(this, R.string.schedule_created_message, Toast.LENGTH_SHORT).show();
            finish();
        } catch (Exception e) {
            Toast.makeText(this, "Error creating schedule!", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    public void saveSchedule() {

        if (!validateBeforeSave()) {
            return;
        }

        if (mSchedule != null) {
            updateSchedule();
        } else {
            createSchedule();
        }
    }

    boolean validateBeforeSave() {

        if (ScheduleHelper.instance().getSelectedMed() == null) {
            mViewPager.setCurrentItem(0);
            showSnackBar(R.string.create_schedule_unselected_med);
            return false;
        }

        for (ScheduleItem i : ScheduleHelper.instance().getScheduleItems()) {
            if (i.routine() == null) {
                mViewPager.setCurrentItem(1);
                showSnackBar(R.string.create_schedule_incomplete_items);
                return false;
            }
        }

        for (ScheduleItem i : ScheduleHelper.instance().getScheduleItems()) {
            if (i.dose() <= 0) {
                mViewPager.setCurrentItem(1);
                showSnackBar(R.string.create_schedule_incomplete_doses);
                return false;
            }
        }

        if (ScheduleHelper.instance().getSchedule().type() == Schedule.SCHEDULE_TYPE_CYCLE
                && (ScheduleHelper.instance().getSchedule().getCycleRest() <= 0
                        || ScheduleHelper.instance().getSchedule().getCycleDays() <= 0)) {
            showSnackBar(R.string.cycle_period_cero_message);
            return false;
        }
        return true;
    }

    private void showSnackBar(int string) {
        SnackbarManager.show(Snackbar.with(getApplicationContext()).actionLabel("OK")
                .actionColor(getResources().getColor(R.color.android_orange_darker)).type(SnackbarType.MULTI_LINE)
                .textColor(getResources().getColor(R.color.white_80)) // change the text color
                .color(getResources().getColor(R.color.android_orange_dark)) // change the background color
                .text(getResources().getString(string)), this);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.schedules, menu);
        removeItem = menu.findItem(R.id.action_remove);
        removeItem.setVisible(mScheduleId != -1 ? true : false);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_remove:
            showDeleteConfirmationDialog(mSchedule);
            return true;
        default:
            finish();
            return true;
        }
    }

    public void onMedicineSelected(Medicine m, boolean step) {

        ScheduleHelper.instance().setSelectedMed(m);

        if (!step) {
            autoStepDone = true;
        }

        if (!autoStepDone) {
            autoStepDone = true;
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    mViewPager.setCurrentItem(1);
                }
            }, 500);
        }

        if (mScheduleId == -1) {
            String titleStart = getString(R.string.title_create_schedule_activity);
            String medName = " (" + m.name() + ")";
            String fullTitle = titleStart + medName;

            SpannableString title = new SpannableString(fullTitle);
            title.setSpan(new RelativeSizeSpan(0.7f), titleStart.length(), titleStart.length() + medName.length(),
                    0);
            title.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.white_50)), titleStart.length(),
                    titleStart.length() + medName.length(), 0);
            getSupportActionBar().setTitle(title);
        }
    }

    public void onScheduleTypeSelected() {
        ((ScheduleTimetableFragment) getViewPagerFragment(2)).onTypeSelected();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mViewPager.setCurrentItem(2);
            }
        }, 500);
    }

    public void onDoseSelectedWithNoMed() {
        mViewPager.setCurrentItem(0);
        Snack.show(getString(R.string.create_schedule_select_med_before_dose), this);
    }

    void showDeleteConfirmationDialog(final Schedule s) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(String.format(getString(R.string.remove_medicine_message_short), s.medicine().name()))
                .setCancelable(true)
                .setPositiveButton(getString(R.string.dialog_yes_option), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        DB.schedules().deleteCascade(s, true);
                        finish();
                    }
                }).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();
    }

    @Override
    public void onPageScrolled(int i, float v, int i2) {

    }

    @Override
    public void onPageSelected(int page) {

    }

    @Override
    public void onPageScrollStateChanged(int i) {

    }

    @Override
    protected void onDestroy() {
        unsubscribeFromEvents();
        ScheduleHelper.instance().clear();
        super.onDestroy();
    }

    Fragment getViewPagerFragment(int position) {
        return getSupportFragmentManager()
                .findFragmentByTag(FragmentUtils.makeViewPagerFragmentName(R.id.pager, position));
    }

    @Override
    protected void onPause() {
        super.onPause();
        overridePendingTransition(0, 0);
    }

    public void onEvent(PersistenceEvents.MedicineAddedEvent event) {
        Log.d("onEvent", event.id + " ----");
        ((SelectMedicineListFragment) getViewPagerFragment(0)).setSelectedMed(event.id);
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter
    //            implements PagerSlidingTabStrip.IconTabProvider
    {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            if (position == 1) {
                return new ScheduleTimetableFragment();
            } /*else if (position == 1) {
              return new ScheduleTypeFragment();
              } */ else if (position == 0) {
                return new SelectMedicineListFragment();

            } else {
                return new ScheduleSummaryFragment();
            }
        }

        @Override
        public CharSequence getPageTitle(int position) {
            if (position == 0) {
                return getString(R.string.medicine);
            } /*else if (position == 1) {
              return getString(R.string.schedule_type);
              }*/ else if (position == 1) {
                return getString(R.string.schedule);
            } else {
                return getString(R.string.summary);
            }
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 3;
        }
    }

}