net.reichholf.dreamdroid.fragment.TimerEditFragment.java Source code

Java tutorial

Introduction

Here is the source code for net.reichholf.dreamdroid.fragment.TimerEditFragment.java

Source

/*  2010 Stephan Reichholf <stephan at reichholf dot net>
 * 
 * Licensed under the Create-Commons Attribution-Noncommercial-Share Alike 3.0 Unported
 * http://creativecommons.org/licenses/by-nc-sa/3.0/
 */

package net.reichholf.dreamdroid.fragment;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;

import net.reichholf.dreamdroid.DreamDroid;
import net.reichholf.dreamdroid.R;
import net.reichholf.dreamdroid.activities.abs.MultiPaneHandler;
import net.reichholf.dreamdroid.fragment.abs.AbstractHttpFragment;
import net.reichholf.dreamdroid.fragment.dialogs.MultiChoiceDialog;
import net.reichholf.dreamdroid.helpers.DateTime;
import net.reichholf.dreamdroid.helpers.ExtendedHashMap;
import net.reichholf.dreamdroid.helpers.Python;
import net.reichholf.dreamdroid.helpers.Statics;
import net.reichholf.dreamdroid.helpers.enigma2.Service;
import net.reichholf.dreamdroid.helpers.enigma2.SimpleResult;
import net.reichholf.dreamdroid.helpers.enigma2.Tag;
import net.reichholf.dreamdroid.helpers.enigma2.Timer;
import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.TimerChangeRequestHandler;

import org.apache.http.NameValuePair;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

import com.fourmob.datetimepicker.date.DatePickerDialog;
import com.sleepbot.datetimepicker.time.RadialPickerLayout;
import com.sleepbot.datetimepicker.time.TimePickerDialog;

//TODO Add Tag Support

/**
 * Activity for Editing existing or initial timers
 *
 * @author sreichholf
 */
public class TimerEditFragment extends AbstractHttpFragment implements MultiChoiceDialog.MultiChoiceDialogListener {

    private static final String TAG = TimerEditFragment.class.getSimpleName();

    private static final int[] sRepeatedValues = { 1, 2, 4, 8, 16, 32, 64 };

    private boolean[] mCheckedDays = { false, false, false, false, false, false, false };

    private boolean mTagsChanged;
    private ArrayList<String> mSelectedTags;

    private ExtendedHashMap mTimer;
    private ExtendedHashMap mTimerOld;

    private EditText mName;
    private EditText mDescription;
    private CheckBox mEnabled;
    private CheckBox mZap;
    private Spinner mAfterevent;
    private Spinner mLocation;
    private TextView mStartDate;
    private TextView mStartTime;
    private TextView mEndDate;
    private TextView mEndTime;
    private TextView mService;
    private TextView mRepeatings;
    private TextView mTags;
    private ProgressDialog mLoadProgress;
    private ProgressDialog mProgress;

    private GetLocationsAndTagsTask mGetLocationsAndTagsTask;

    private int mBegin;
    private int mEnd;

    private class GetLocationsAndTagsTask extends AsyncTask<Void, String, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            if (DreamDroid.getLocations().size() == 0) {
                if (isCancelled())
                    return false;
                publishProgress(getText(R.string.locations) + " - " + getText(R.string.fetching_data));
                DreamDroid.loadLocations(getHttpClient());
            }

            if (DreamDroid.getTags().size() == 0) {
                if (isCancelled())
                    return false;
                publishProgress(getText(R.string.tags) + " - " + getText(R.string.fetching_data));
                DreamDroid.loadTags(getHttpClient());
            }

            return true;
        }

        @Override
        protected void onProgressUpdate(String... progress) {
            if (isCancelled())
                return;
            if (mLoadProgress != null) {
                if (!mLoadProgress.isShowing()) {
                    mLoadProgress = ProgressDialog.show(getAppCompatActivity(),
                            getText(R.string.loading).toString(), progress[0]);
                } else {
                    mLoadProgress.setMessage(progress[0]);
                }
            } else {
                mLoadProgress = ProgressDialog.show(getAppCompatActivity(), getText(R.string.loading).toString(),
                        progress[0]);
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            if (isCancelled())
                return;
            if (mLoadProgress.isShowing()) {
                mLoadProgress.dismiss();
            }
            reload();
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initTitles(getString(R.string.timer));
    }

    @Override
    public void onDestroy() {
        if (mGetLocationsAndTagsTask != null)
            mGetLocationsAndTagsTask.cancel(true);
        super.onDestroy();
    }

    @SuppressWarnings("unchecked")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.timer_edit, container, false);

        mName = (EditText) view.findViewById(R.id.EditTextTitle);
        mDescription = (EditText) view.findViewById(R.id.EditTextDescription);
        mEnabled = (CheckBox) view.findViewById(R.id.CheckBoxEnabled);
        mZap = (CheckBox) view.findViewById(R.id.CheckBoxZap);
        mAfterevent = (Spinner) view.findViewById(R.id.SpinnerAfterEvent);
        mLocation = (Spinner) view.findViewById(R.id.SpinnerLocation);
        mStartDate = (TextView) view.findViewById(R.id.TextViewBeginDate);
        mStartTime = (TextView) view.findViewById(R.id.TextViewBeginTime);
        mEndDate = (TextView) view.findViewById(R.id.TextViewEndDate);
        mEndTime = (TextView) view.findViewById(R.id.TextViewEndTime);
        mRepeatings = (TextView) view.findViewById(R.id.TextViewRepeated);
        mService = (TextView) view.findViewById(R.id.TextViewService);
        mTags = (TextView) view.findViewById(R.id.TextViewTags);

        // onClickListeners
        registerOnClickListener(mService, Statics.ITEM_PICK_SERVICE);
        registerOnClickListener(mStartDate, Statics.ITEM_PICK_BEGIN_DATE);
        registerOnClickListener(mStartTime, Statics.ITEM_PICK_BEGIN_TIME);
        registerOnClickListener(mEndDate, Statics.ITEM_PICK_END_DATE);
        registerOnClickListener(mEndTime, Statics.ITEM_PICK_END_TIME);
        registerOnClickListener(mRepeatings, Statics.ITEM_PICK_REPEATED);
        registerOnClickListener(mTags, Statics.ITEM_PICK_TAGS);

        mAfterevent.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
                mTimer.put(Timer.KEY_AFTER_EVENT, Integer.valueOf(position).toString());
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // Auto is the default
                mAfterevent.setSelection(Timer.Afterevents.AUTO.intValue());
            }
        });

        mLocation.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
                mTimer.put(Timer.KEY_LOCATION, DreamDroid.getLocations().get(position));
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                // TODO implement some nothing-selected-handler for locations
            }
        });

        // Initialize if savedInstanceState won't and instance was not retained
        if (savedInstanceState == null && mTimer == null && mTimerOld == null) {
            HashMap<String, Object> map = (HashMap<String, Object>) getArguments().get(sData);
            ExtendedHashMap data = new ExtendedHashMap();
            data.putAll(map);

            mTimer = new ExtendedHashMap();
            mTimer.putAll((HashMap<String, Object>) data.get("timer"));

            if (Intent.ACTION_EDIT.equals(getArguments().get("action"))) {
                mTimerOld = mTimer.clone();
            } else {
                mTimerOld = null;
            }

            mSelectedTags = new ArrayList<>();

            if (DreamDroid.getLocations().size() == 0 || DreamDroid.getTags().size() == 0) {
                mGetLocationsAndTagsTask = new GetLocationsAndTagsTask();
                mGetLocationsAndTagsTask.execute();
            } else {
                reload();
            }
        } else if (savedInstanceState != null) {
            mTimer = savedInstanceState.getParcelable("timer");
            mTimerOld = savedInstanceState.getParcelable("timerOld");
            mSelectedTags = new ArrayList<>(Arrays.asList(savedInstanceState.getStringArray("selectedTags")));
            if (mTimer != null) {
                reload();
            }
        } else {
            reload();
        }

        registerFab(R.id.fab_save, view, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onItemSelected(Statics.ITEM_SAVE);
            }
        });
        return view;
    }

    public void createOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.cancel, menu);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Statics.REQUEST_PICK_SERVICE) {
            if (resultCode == Activity.RESULT_OK) {
                ExtendedHashMap map = new ExtendedHashMap();
                map.putAll((HashMap<String, Object>) data.getSerializableExtra(sData));

                mTimer.put(Timer.KEY_SERVICE_NAME, map.getString(Service.KEY_NAME));
                mTimer.put(Timer.KEY_REFERENCE, map.getString(Service.KEY_REFERENCE));
                mService.setText(mTimer.getString(Timer.KEY_SERVICE_NAME));
            }
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putParcelable("timer", mTimer);
        outState.putParcelable("timerOld", mTimerOld);

        String[] selectedTags;
        if (mSelectedTags != null) {
            selectedTags = new String[mSelectedTags.size()];
            mSelectedTags.toArray(selectedTags);
        } else {
            selectedTags = new String[0];
        }
        outState.putStringArray("selectedTags", selectedTags);

        if (mProgress != null) {
            if (mProgress.isShowing()) {
                mProgress.dismiss();
            }
        }

        super.onSaveInstanceState(outState);
    }

    protected void pickRepeatings() {
        CharSequence[] days = getResources().getTextArray(R.array.weekdays);
        MultiChoiceDialog f = MultiChoiceDialog.newInstance(R.string.choose_days, days, mCheckedDays);
        getMultiPaneHandler().showDialogFragment(f, "dialog_select_repeatings");
    }

    protected void pickTags() {
        CharSequence[] tags = new CharSequence[DreamDroid.getTags().size()];
        boolean[] selectedTags = new boolean[DreamDroid.getTags().size()];

        int tc = 0;
        for (String tag : DreamDroid.getTags()) {
            tags[tc] = tag;
            selectedTags[tc] = mSelectedTags.contains(tag);
            tc++;
        }

        mTagsChanged = false;

        MultiChoiceDialog f = MultiChoiceDialog.newInstance(R.string.choose_tags, tags, selectedTags, R.string.ok,
                R.string.cancel);

        getMultiPaneHandler().showDialogFragment(f, "dialog_select_tags");
    }

    /**
     * @param v
     * @param id
     */
    protected void registerOnClickListener(View v, final int id) {
        v.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onItemSelected(id);
            }
        });
    }

    /**
     * @param id
     */
    protected boolean onItemSelected(int id) {
        Bundle args;
        boolean consumed = false;
        Calendar calendar = null;
        switch (id) {
        case Statics.ITEM_SAVE:
            saveTimer();
            consumed = true;
            break;

        case Statics.ITEM_CANCEL:
            finish(Activity.RESULT_CANCELED);
            consumed = true;
            break;

        case Statics.ITEM_PICK_SERVICE:
            pickService();
            consumed = true;
            break;

        case Statics.ITEM_PICK_BEGIN_DATE:
            calendar = getCalendar(mBegin);
            DatePickerDialog datePickerDialogBegin = DatePickerDialog
                    .newInstance(new DatePickerDialog.OnDateSetListener() {
                        @Override
                        public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) {
                            TimerEditFragment.this.onDateSet(true, year, month, day);
                        }
                    }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                            calendar.get(Calendar.DAY_OF_MONTH), true);
            getMultiPaneHandler().showDialogFragment(datePickerDialogBegin, "dialog_pick_begin_date");
            consumed = true;
            break;

        case Statics.ITEM_PICK_BEGIN_TIME:
            calendar = getCalendar(mBegin);
            TimePickerDialog timePickerDialogBegin = TimePickerDialog
                    .newInstance(new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(RadialPickerLayout radialPickerLayout, int hour, int minute) {
                            TimerEditFragment.this.onTimeSet(true, hour, minute);
                        }
                    }, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), true, true);
            getMultiPaneHandler().showDialogFragment(timePickerDialogBegin, "dialog_pick_begin_time");
            consumed = true;
            break;

        case Statics.ITEM_PICK_END_DATE:
            calendar = getCalendar(mEnd);
            DatePickerDialog datePickerDialogEnd = DatePickerDialog
                    .newInstance(new DatePickerDialog.OnDateSetListener() {
                        @Override
                        public void onDateSet(DatePickerDialog datePickerDialog, int year, int month, int day) {
                            TimerEditFragment.this.onDateSet(false, year, month, day);
                        }
                    }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                            calendar.get(Calendar.DAY_OF_MONTH), true);
            getMultiPaneHandler().showDialogFragment(datePickerDialogEnd, "dialog_pick_end_date");
            consumed = true;
            break;

        case Statics.ITEM_PICK_END_TIME:
            calendar = getCalendar(mEnd);
            TimePickerDialog timePickerDialogEnd = TimePickerDialog
                    .newInstance(new TimePickerDialog.OnTimeSetListener() {
                        @Override
                        public void onTimeSet(RadialPickerLayout radialPickerLayout, int hour, int minute) {
                            TimerEditFragment.this.onTimeSet(false, hour, minute);
                        }
                    }, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), true, true);
            getMultiPaneHandler().showDialogFragment(timePickerDialogEnd, "dialog_pick_end_time");
            consumed = true;
            break;

        case Statics.ITEM_PICK_REPEATED:
            pickRepeatings();
            consumed = true;
            break;

        case Statics.ITEM_PICK_TAGS:
            pickTags();
            consumed = true;
            break;

        default:
            consumed = super.onItemSelected(id);
            break;
        }

        return consumed;
    }

    /**
     *
     */
    private void pickService() {
        ServiceListFragment f = new ServiceListFragment();
        Bundle args = new Bundle();

        ExtendedHashMap data = new ExtendedHashMap();
        data.put(Service.KEY_REFERENCE, "default");

        args.putSerializable(sData, data);
        args.putString("action", Intent.ACTION_PICK);

        f.setArguments(args);
        f.setTargetFragment(this, Statics.REQUEST_PICK_SERVICE);
        ((MultiPaneHandler) getAppCompatActivity()).showDetails(f, true);
    }

    /**
     * Set the GUI-Content from <code>mTimer</code>
     */
    protected void reload() {
        // Name
        mName.setText(mTimer.getString(Timer.KEY_NAME));
        mName.setHint(R.string.title);

        // Description
        mDescription.setText(mTimer.getString(Timer.KEY_DESCRIPTION));
        mDescription.setHint(R.string.description);

        // Enabled
        int disabled = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_DISABLED));
        if (disabled == 0) {
            mEnabled.setChecked(true);
        } else {
            mEnabled.setChecked(false);
        }

        int zap = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_JUST_PLAY));
        if (zap == 1) {
            mZap.setChecked(true);
        } else {
            mZap.setChecked(false);
        }

        mService.setText(mTimer.getString(Timer.KEY_SERVICE_NAME));

        // Afterevents
        ArrayAdapter<CharSequence> aaAfterevent = ArrayAdapter.createFromResource(getAppCompatActivity(),
                R.array.afterevents, android.R.layout.simple_spinner_item);
        aaAfterevent.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mAfterevent.setAdapter(aaAfterevent);

        int aeValue = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_AFTER_EVENT));
        mAfterevent.setSelection(aeValue);

        // Locations
        ArrayAdapter<String> aaLocations = new ArrayAdapter<>(getAppCompatActivity(),
                android.R.layout.simple_spinner_item, DreamDroid.getLocations());
        aaLocations.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mLocation.setAdapter(aaLocations);

        String timerLoc = mTimer.getString(Timer.KEY_LOCATION);
        for (int i = 0; i < DreamDroid.getLocations().size(); i++) {
            String loc = DreamDroid.getLocations().get(i);

            if (timerLoc != null) {
                if (timerLoc.equals(loc)) {
                    mLocation.setSelection(i);
                }
            }
        }

        // Start and Endtime
        mBegin = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_BEGIN));
        mEnd = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_END));
        Date dateBegin = new Date(((long) mBegin) * 1000);
        Date dateEnd = new Date(((long) mEnd) * 1000);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");

        mStartDate.setText(dateFormat.format(dateBegin));
        mStartTime.setText(timeFormat.format(dateBegin));
        mEndDate.setText(dateFormat.format(dateEnd));
        mEndTime.setText(timeFormat.format(dateEnd));

        // Repeatings
        int repeatedValue = 0;
        try {
            repeatedValue = DateTime.parseTimestamp(mTimer.getString(Timer.KEY_REPEATED));
        } catch (NumberFormatException ex) {
        }

        String repeatedText = getRepeated(repeatedValue);
        mRepeatings.setText(repeatedText);

        String text = mTimer.getString(Timer.KEY_TAGS);
        if (text == null) {
            text = "";
        }
        mTags.setText(text);
        String[] tags = text.split(" ");
        Collections.addAll(mSelectedTags, tags);
    }

    /**
     * Interpret the repeated int-value by bit-shifting it
     *
     * @param value The int-value for to-repeat-days
     * @return All days selected for repeatings in "Mo, Tu, Fr"-style
     */
    private String getRepeated(int value) {
        String text = "";
        CharSequence[] daysShort = getResources().getTextArray(R.array.weekdays_short);

        for (int i = 0; i < sRepeatedValues.length; i++) {
            boolean checked = false;

            if ((value & 1) == 1) {
                checked = true;
                if (!text.equals("")) {
                    text = text.concat(", ");
                }
                text = text.concat((String) daysShort[i]);
            }
            mCheckedDays[i] = checked;

            value = (value >> 1);
        }

        if (text.equals("")) {
            text = (String) getText(R.string.none);
        }
        return text;
    }

    /**
     * Applies repeated settings to a timer
     *
     * @param checkedDays <code>boolean[]> of checked days for timer-repeatings
     * @param timer       The acutal timer
     * @return The string to set for the GUI-Label
     */
    private String setRepeated(boolean[] checkedDays, ExtendedHashMap timer) {
        String text = "";
        int value = 0;
        CharSequence[] daysShort = getResources().getTextArray(R.array.weekdays_short);

        for (int i = 0; i < checkedDays.length; i++) {
            if (checkedDays[i]) {
                if (!text.equals("")) {
                    text = text.concat(", ");
                }

                text = text.concat((String) daysShort[i]);
                value += sRepeatedValues[i];
            }
        }

        String repeated = Integer.valueOf(value).toString();
        timer.put(Timer.KEY_REPEATED, repeated);

        if (value == 31) {
            text = (String) getText(R.string.mo_to_fr);
        } else if (value == 127) {
            text = (String) getText(R.string.daily);
        }

        if (text.equals("")) {
            text = (String) getText(R.string.none);
        }

        return text;
    }

    /**
     * Apply GUI-values to the timer. Applies Name, Description, Enabled and
     * Afterevent from the GUI-Elements to <code>mTimer</code>
     */
    private void applyViewValues() {
        mTimer.put(Timer.KEY_NAME, mName.getText().toString());
        mTimer.put(Timer.KEY_DESCRIPTION, mDescription.getText().toString());

        if (mEnabled.isChecked()) {
            mTimer.put(Timer.KEY_DISABLED, "0");
        } else {
            mTimer.put(Timer.KEY_DISABLED, "1");
        }

        if (mZap.isChecked()) {
            mTimer.put(Timer.KEY_JUST_PLAY, "1");
        } else {
            mTimer.put(Timer.KEY_JUST_PLAY, "0");
        }

        String ae = Integer.valueOf(mAfterevent.getSelectedItemPosition()).toString();
        mTimer.put(Timer.KEY_AFTER_EVENT, ae);
    }

    /**
     * Save the current timer on the target device
     */
    private void saveTimer() {
        Log.i(TAG, "saveTimer()");
        if (mProgress != null) {
            if (mProgress.isShowing()) {
                mProgress.dismiss();
            }
        }
        Activity activtiy = getAppCompatActivity();
        mProgress = ProgressDialog.show(activtiy, "", getText(R.string.saving), true);

        applyViewValues();
        ArrayList<NameValuePair> params = Timer.getSaveParams(mTimer, mTimerOld);
        execSimpleResultTask(new TimerChangeRequestHandler(), params);
    }

    @Override
    public void onSimpleResult(boolean success, ExtendedHashMap result) {
        if (mProgress != null) {
            mProgress.dismiss();
            mProgress = null;
        }
        super.onSimpleResult(success, result);

        if (Python.TRUE.equals(result.getString(SimpleResult.KEY_STATE))) {
            finish(Activity.RESULT_OK);
        }
    }

    /**
     * Apply the values of the TimePicker for the Timer-Begin to
     * <code>mTimer</code>
     */
    private void updateBegin(Calendar cal) {
        mBegin = (int) (cal.getTimeInMillis() / 1000);
        String timestamp = Long.valueOf(mBegin).toString();
        mTimer.put(Timer.KEY_BEGIN, timestamp);
        mTimer.put(Timer.KEY_BEGIN_READEABLE, DateTime.getYearDateTimeString(timestamp));
    }

    /**
     * Apply the values of the TimePicker for the Timer-End to
     * <code>mTimer</code>
     */
    private void updateEnd(Calendar cal) {
        mEnd = (int) (cal.getTimeInMillis() / 1000);
        String timestamp = Long.valueOf(mEnd).toString();
        mTimer.put(Timer.KEY_END, timestamp);
        mTimer.put(Timer.KEY_END_READABLE, DateTime.getYearDateTimeString(timestamp));
    }

    @Override
    public void onMultiChoiceDialogSelection(String dialogTag, DialogInterface dialog, Integer[] selected) {
        if ("dialog_select_tags".equals(dialogTag)) {
            ArrayList<String> tags = DreamDroid.getTags();
            ArrayList<String> selectedTags = new ArrayList<>();
            for (Integer which : selected) {
                selectedTags.add(tags.get(which));
            }
            mTagsChanged = !selectedTags.equals(mSelectedTags);
            mSelectedTags = selectedTags;
        } else if ("dialog_select_repeatings".equals(dialogTag)) {
            for (int i = 0; i < mCheckedDays.length; ++i) {
                mCheckedDays[i] = false;
            }
            for (Integer which : selected) {
                mCheckedDays[which] = true;
            }
            String text = setRepeated(mCheckedDays, mTimer);
            mRepeatings.setText(text);
        }
    }

    @Override
    public void onMultiChoiceDialogFinish(String dialogTag, int result) {
        if ("dialog_select_tags".equals(dialogTag) && mTagsChanged) {
            String tags = Tag.implodeTags(mSelectedTags);
            mTimer.put(Timer.KEY_TAGS, tags);
            mTags.setText(tags);
        }
    }

    private Calendar getCalendar(int time) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis((long) time * 1000);
        return cal;
    }

    public void onDateSet(boolean isBegin, int year, int month, int day) {
        int time = isBegin ? mBegin : mEnd;

        Calendar cal = getCalendar(time);

        if (cal.get(Calendar.YEAR) == year && cal.get(Calendar.MONTH) == month && cal.get(Calendar.DATE) == day)
            return;
        cal.set(year, month, day);

        TextView dateView = isBegin ? mStartDate : mEndDate;
        SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateView.setText(dayFormat.format(cal.getTime()));

        onTimeChanged(isBegin, cal);
    }

    public void onTimeSet(boolean isBegin, int hourOfDay, int minute) {
        int time = isBegin ? mBegin : mEnd;
        Calendar cal = getCalendar(time);
        if (cal.get(Calendar.HOUR_OF_DAY) == hourOfDay && cal.get(Calendar.MINUTE) == minute)
            return;
        cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
        cal.set(Calendar.MINUTE, minute);

        TextView timeView = isBegin ? mStartTime : mEndTime;
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
        timeView.setText(timeFormat.format(cal.getTime()));

        onTimeChanged(isBegin, cal);
    }

    private void onTimeChanged(boolean isBegin, Calendar cal) {
        if (isBegin)
            updateBegin(cal);
        else
            updateEnd(cal);
    }
}