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

Java tutorial

Introduction

Here is the source code for es.usc.citius.servando.calendula.activities.CalendarActivity.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.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.util.Pair;
import android.support.v4.widget.NestedScrollView;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.mikepenz.community_material_typeface_library.CommunityMaterial;
import com.mikepenz.iconics.IconicsDrawable;
import com.roomorama.caldroid.CaldroidFragment;
import com.roomorama.caldroid.CaldroidGridAdapter;
import com.roomorama.caldroid.CaldroidListener;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import es.usc.citius.servando.calendula.CalendulaActivity;
import es.usc.citius.servando.calendula.R;
import es.usc.citius.servando.calendula.database.DB;
import es.usc.citius.servando.calendula.persistence.Medicine;
import es.usc.citius.servando.calendula.persistence.Patient;
import es.usc.citius.servando.calendula.persistence.PickupInfo;
import es.usc.citius.servando.calendula.scheduling.PickupReminderMgr;
import es.usc.citius.servando.calendula.util.AvatarMgr;
import es.usc.citius.servando.calendula.util.PickupUtils;

public class CalendarActivity extends CalendulaActivity {

    public static final int ACTION_SHOW_REMINDERS = 1;

    private static DateFormat dtf2 = new SimpleDateFormat("dd/MMM");
    private Pair<LocalDate, List<PickupInfo>> bestDay;
    static PickupUtils pickupUtils;

    DateTime from;
    DateTime to;
    String df;
    Patient patient;
    Patient selectedPatient;
    int selectedPatientIdx = 0;
    long selectedPatientId;
    List<Patient> pats;
    Date selectedDate = null;
    CharSequence bestDayText;

    View bottomSheet;
    TextView title;
    AppBarLayout appBarLayout;
    CollapsingToolbarLayout toolbarLayout;
    TextView subtitle;
    ImageView avatar;
    CaldroidFragment caldroidFragment;
    View topBg;
    NestedScrollView nestedScrollView;
    View titleCollapsedContainer;

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

        pats = DB.patients().findAll();
        patient = DB.patients().getActive(this);

        setupStatusBar(Color.TRANSPARENT);
        setupToolbar("", Color.TRANSPARENT, Color.WHITE);
        toolbar.setTitleTextColor(Color.WHITE);

        appBarLayout = (AppBarLayout) findViewById(R.id.appbar);
        toolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        titleCollapsedContainer = findViewById(R.id.collapsed_title_container);

        topBg = findViewById(R.id.imageView5);
        subtitle = (TextView) findViewById(R.id.routine_name);
        title = (TextView) findViewById(R.id.routine_name_title);
        avatar = (ImageView) findViewById(R.id.patient_avatar_title);
        nestedScrollView = (NestedScrollView) findViewById(R.id.nestedScrollView);

        df = getString(R.string.pickup_date_format);
        from = DateTime.now().minusMonths(3);
        to = DateTime.now().plusMonths(3);
        bottomSheet = findViewById(R.id.pickup_list_container);
        bottomSheet.setVisibility(View.INVISIBLE);

        setupPatientSpinner();
        onPatientUpdate();
        findViewById(R.id.close_pickup_list).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                hideBottomSheet();
            }
        });
        checkIntent();
    }

    private void setupPatientSpinner() {
        String[] names = new String[pats.size() + 1];

        names[0] = "Todos";
        for (int i = 0; i < pats.size(); i++) {
            names[i + 1] = pats.get(i).name();
        }

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.toolbar_spinner_item, names);
        adapter.setDropDownViewResource(R.layout.toolbar_spinner_item);
        Spinner spinner = (Spinner) findViewById(R.id.toolbar_spinner);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                selectedPatientIdx = i;
                onPatientUpdate();
            }

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

            }
        });

    }

    private void onPatientUpdate() {
        if (selectedPatientIdx == 0) {
            topBg.setBackgroundColor(getResources().getColor(R.color.dark_grey_home));
            avatar.setImageDrawable(new IconicsDrawable(CalendarActivity.this)
                    .icon(CommunityMaterial.Icon.cmd_account_multiple).color(Color.WHITE).paddingDp(6).sizeDp(48));
        } else {
            int pIndex = selectedPatientIdx - 1;
            selectedPatient = pats.get(pIndex);
            topBg.setBackgroundColor(selectedPatient.color());

            selectedPatientId = selectedPatient.id();
            avatar.setImageResource(AvatarMgr.res(selectedPatient.avatar()));
        }

        new UpdatePickupsTask().execute();
    }

    void setupNewCalendar() {
        caldroidFragment = new CaldroidSampleCustomFragment();
        Bundle args = new Bundle();
        DateTime now = DateTime.now();
        args.putInt(CaldroidFragment.MONTH, now.getMonthOfYear());
        args.putInt(CaldroidFragment.YEAR, now.getYear());
        args.putBoolean(CaldroidFragment.SHOW_NAVIGATION_ARROWS, false);
        args.putBoolean(CaldroidFragment.SIX_WEEKS_IN_CALENDAR, false);
        args.putInt(CaldroidFragment.START_DAY_OF_WEEK, CaldroidFragment.MONDAY);
        args.putInt(CaldroidFragment.THEME_RESOURCE, R.style.CaldroidDefaultNoGrid);
        caldroidFragment.setArguments(args);
        FragmentTransaction t = getSupportFragmentManager().beginTransaction();
        t.replace(R.id.calendar, caldroidFragment);
        t.commit();

        final CaldroidListener listener = new CaldroidListener() {

            @Override
            public void onSelectDate(Date date, View view) {
                LocalDate d = LocalDate.fromDateFields(date);
                onDaySelected(d);
                if (bestDay != null && bestDay.first != null && bestDay.first.equals(d)) {
                    //Toast.makeText(CalendarActivity.this, "Best day!", Toast.LENGTH_SHORT).show();
                    AlertDialog.Builder builder = new AlertDialog.Builder(CalendarActivity.this);
                    builder.setTitle(R.string.best_date_recommendation_title).setPositiveButton(
                            getString(R.string.driving_warning_gotit), new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int which) {
                                    dialog.dismiss();
                                }
                            });
                    AlertDialog alertDialog = builder.create();
                    alertDialog.setMessage(bestDayText);
                    alertDialog.show();
                }
            }

            @Override
            public void onChangeMonth(int month, int year) {
                DateTime date = DateTime.now().withYear(year).withMonthOfYear(month);
                subtitle.setText(date.toString("MMMM YYYY").toUpperCase());
            }

            @Override
            public void onLongClickDate(Date date, View view) {

            }

            @Override
            public void onCaldroidViewCreated() {
                caldroidFragment.getView().findViewById(R.id.calendar_title_view).setVisibility(View.GONE);
                caldroidFragment.getMonthTitleTextView().setVisibility(View.GONE);
            }

        };

        caldroidFragment.setCaldroidListener(listener);
        this.bestDay = pickupUtils.getBestDay();
        this.bestDayText = getBestDayText();

        if (this.bestDay != null && this.bestDay.first != null) {
            //Toast.makeText(CalendarActivity.this, "Best day: " + bestDay.first.toString("dd/MM/YY"), Toast.LENGTH_SHORT).show();
            caldroidFragment.setBackgroundDrawableForDate(
                    new ColorDrawable(getResources().getColor(R.color.android_green_light)),
                    this.bestDay.first.toDate());
        }

        caldroidFragment.refreshView();
    }

    @Override
    protected void onDestroy() {
        selectedDate = null;
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.calendar, menu);

        IconicsDrawable icon = new IconicsDrawable(this, CommunityMaterial.Icon.cmd_information_outline).sizeDp(48)
                .paddingDp(6).color(Color.WHITE);

        menu.getItem(0).setIcon(icon);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_best_day:
            //onBestDaySelected();
            return true;
        default:
            return false;
        }
    }

    private void onActivateReminder(final LocalDate best) {

        AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                }).setTitle(R.string.best_date_reminder)
                .setSingleChoiceItems(getResources().getStringArray(R.array.calendar_pickup_reminder_values), -1,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                PickupReminderMgr.instance().setCheckPickupsAlarm(CalendarActivity.this,
                                        best.minusDays(which + 1));
                                Toast.makeText(CalendarActivity.this, "Recordatorio activado!", Toast.LENGTH_SHORT)
                                        .show();
                                dialog.dismiss();
                            }
                        })
                .create();
        alertDialog.show();
    }

    public CharSequence addPickupList(CharSequence msg, List<PickupInfo> pks) {

        Paint textPaint = new Paint();
        //obviously, we have to set textSize into Paint object
        textPaint.setTextSize(getResources().getDimensionPixelOffset(R.dimen.medium_font_size));
        Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();

        for (PickupInfo p : pks) {
            Patient patient = pickupUtils.getPatient(p);
            int color = patient.color();
            String str = "       " + p.medicine().name() + " (" + dtf2.format(p.from().toDate()) + " - "
                    + dtf2.format(p.to().toDate()) + ")\n";
            Spannable text = new SpannableString(str);
            text.setSpan(new ForegroundColorSpan(color), 0, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            Drawable d = getResources().getDrawable(AvatarMgr.res(patient.avatar()));
            d.setBounds(0, 0, fontMetrics.bottom, fontMetrics.bottom);
            ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
            text.setSpan(span, 0, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
            msg = TextUtils.concat(msg, text);
        }
        return msg;
    }

    private void checkIntent() {

        int action = getIntent().getIntExtra("action", -1);
        if (action == ACTION_SHOW_REMINDERS) {
            //onBestDaySelected();
        }
    }

    private boolean onDaySelected(LocalDate date) {
        selectedDate = date.toDateTimeAtStartOfDay().toDate();
        return showPickupsInfo(date);
    }

    private boolean showPickupsInfo(final LocalDate date) {
        final List<PickupInfo> from = DB.pickups().findByFrom(date, true);
        if (!from.isEmpty()) {

            TextView title = ((TextView) bottomSheet.findViewById(R.id.bottom_sheet_title));

            LayoutInflater i = getLayoutInflater();
            LinearLayout list = (LinearLayout) findViewById(R.id.pickup_list);
            list.removeAllViews();
            for (final PickupInfo p : from) {

                Medicine m = DB.medicines().findById(p.medicine().getId());
                Patient pat = DB.patients().findById(m.patient().id());

                if (selectedPatientIdx == 0 || pat.id() == selectedPatientId) {

                    View v = i.inflate(R.layout.calendar_pickup_list_item, null);
                    TextView tv1 = ((TextView) v.findViewById(R.id.textView));
                    TextView tv2 = ((TextView) v.findViewById(R.id.textView2));
                    ImageView avatar = ((ImageView) v.findViewById(R.id.avatar));
                    String interval = getResources().getString(R.string.pickup_interval, p.to().toString(df));

                    if (p.taken()) {
                        interval += " ";
                        tv1.setAlpha(0.5f);
                    } else {
                        tv1.setAlpha(1f);
                        tv2.setAlpha(1f);
                    }

                    tv1.setText(p.medicine().name());
                    tv2.setText(interval);
                    avatar.setImageResource(AvatarMgr.res(pat.avatar()));

                    tv1.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            p.taken(!p.taken());
                            DB.pickups().save(p);
                            showPickupsInfo(date);
                        }
                    });
                    list.addView(v);
                }
            }
            nestedScrollView.scrollBy(0, bottomSheet.getHeight());
            showBottomSheet();
            int total = list.getChildCount();
            title.setText(
                    total + " " + getResources().getString(R.string.title_pickups_bottom_sheet, date.toString(df)));
            appBarLayout.setExpanded(false, true);
            return true;
        }
        return false;
    }

    public void showBottomSheet() {
        bottomSheet.setVisibility(View.VISIBLE);
    }

    public void hideBottomSheet() {
        LinearLayout list = (LinearLayout) findViewById(R.id.pickup_list);
        list.removeAllViews();
        appBarLayout.setExpanded(true, true);
        bottomSheet.setVisibility(View.INVISIBLE);
    }

    @Override
    public void onBackPressed() {
        if (bottomSheet.getVisibility() == View.VISIBLE) {
            hideBottomSheet();
        } else {
            super.onBackPressed();
        }
    }

    public CharSequence getBestDayText() {

        final List<PickupInfo> urgent = pickupUtils.urgentMeds();
        Pair<LocalDate, List<PickupInfo>> best = pickupUtils.getBestDay();

        final List<PickupInfo> next = (best == null || best.first == null) ? new ArrayList<PickupInfo>()
                : best.second;

        CharSequence msg = new SpannableString("No hai medicinas que recoger");
        LocalDate today = LocalDate.now();

        // there are not urgent meds, but there are others to pickup
        if (urgent.isEmpty() && best != null) {

            //            Log.d("Calendar", "Urgent: " + urgent.size());
            //            Log.d("Calendar", "Next: " + next.size());

            Log.d("Calendar", "there are not urgent meds, but there are others to pickup");
            if (next.size() > 1) {
                msg = new SpannableString(getString(R.string.best_single_day_messge,
                        best.first.toString(getString(R.string.best_date_format)), next.size()) + "\n\n");
            } else {
                msg = new SpannableString(getString(R.string.best_single_day_messge_one_med,
                        best.first.toString(getString(R.string.best_date_format))) + "\n\n");
            }
            msg = addPickupList(msg, next);
        }

        // there are urgent meds
        Log.d("Calendar", "there are urgent meds");
        if (!urgent.isEmpty()) {
            // and others
            Log.d("Calendar", "and others");
            if (best != null) {

                String bestStr = best.equals(LocalDate.now().plusDays(1))
                        ? getString(R.string.calendar_date_tomorrow)
                        : best.first.toString(getString(R.string.best_date_format));

                // and the others date is near
                Log.d("Calendar", "and the others date is near");
                if (today.plusDays(3).isAfter(best.first)) {
                    List<PickupInfo> all = new ArrayList<>();
                    all.addAll(urgent);
                    all.addAll(next);
                    msg = new SpannableString(
                            getString(R.string.best_single_day_messge, bestStr, all.size()) + "\n\n");
                    msg = addPickupList(msg, all);
                }
                // and the others date is not near
                else {

                    Log.d("Calendar", "and the others date is not near");
                    msg = addPickupList(new SpannableString(getString(R.string.pending_meds_msg) + "\n\n"), urgent);

                    msg = TextUtils.concat(msg, new SpannableString("\n"));
                    if (next.size() > 1) {
                        Log.d("Calendar", " size > 1");
                        msg = TextUtils.concat(msg,
                                getString(R.string.best_single_day_messge_after_pending, bestStr, next.size())
                                        + "\n\n");
                    } else {
                        Log.d("Calendar", " size <= 1");
                        msg = TextUtils.concat(msg,
                                getString(R.string.best_single_day_messge_after_pending_one_med, bestStr) + "\n\n");
                    }
                    msg = addPickupList(msg, next);
                }
            } else {
                Log.d("Calendar", " there are only urgent meds");
                // there are only urgent meds
                msg = addPickupList(getString(R.string.pending_meds_msg) + "\n\n", urgent);
            }
        }

        Log.d("BEST_DAY", msg.toString());
        return msg;
    }

    public static class CaldroidSampleCustomFragment extends CaldroidFragment {
        @Override
        public CaldroidGridAdapter getNewDatesGridAdapter(int month, int year) {
            return new CaldroidSampleCustomAdapter(getActivity(), month, year, getCaldroidData(), extraData,
                    pickupUtils);
        }
    }

    public class UpdatePickupsTask extends AsyncTask<Void, Void, Void> {

        ProgressDialog dialog;

        @Override
        protected Void doInBackground(Void... params) {
            pickupUtils = new PickupUtils(
                    selectedPatientIdx == 0 ? DB.pickups().findAll() : DB.pickups().findByPatient(selectedPatient));
            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(CalendarActivity.this);
            dialog.setIndeterminate(true);
            dialog.setMessage("Actualizando calendario...");
            dialog.show();
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            if (dialog.isShowing()) {
                dialog.dismiss();
            }
            setupNewCalendar();
        }
    }

}