com.jaspersoft.android.jaspermobile.ui.view.widget.ScheduleFormView.java Source code

Java tutorial

Introduction

Here is the source code for com.jaspersoft.android.jaspermobile.ui.view.widget.ScheduleFormView.java

Source

/*
 * Copyright  2016 TIBCO Software,Inc.All rights reserved.
 * http://community.jaspersoft.com/project/jaspermobile-android
 *
 * Unless you have purchased a commercial license agreement from TIBCO Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of TIBCO Jaspersoft Mobile for Android.
 *
 * TIBCO Jaspersoft Mobile is free software:you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation,either version 3of the License,or
 * (at your option)any later version.
 *
 * TIBCO Jaspersoft Mobile 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with TIBCO Jaspersoft Mobile for Android.If not,see
 * <http://www.gnu.org/licenses/lgpl>.
 */

package com.jaspersoft.android.jaspermobile.ui.view.widget;

import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.jaspersoft.android.jaspermobile.R;
import com.jaspersoft.android.jaspermobile.dialog.CalendarDayDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.CalendarMonthDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.DateDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.IntervalUnitDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.NumberDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.OutputFormatDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.RecurrenceTypeDialogFragment;
import com.jaspersoft.android.jaspermobile.dialog.ValueInputDialogFragment;
import com.jaspersoft.android.jaspermobile.ui.contract.ScheduleFormContract;
import com.jaspersoft.android.jaspermobile.ui.entity.job.CalendarViewRecurrence;
import com.jaspersoft.android.jaspermobile.ui.entity.job.JobFormViewBundle;
import com.jaspersoft.android.jaspermobile.ui.entity.job.JobFormViewEntity;
import com.jaspersoft.android.jaspermobile.ui.entity.job.NoneViewRecurrence;
import com.jaspersoft.android.jaspermobile.ui.entity.job.SimpleViewRecurrence;
import com.jaspersoft.android.jaspermobile.widget.DateTimeView;

import org.androidannotations.annotations.CheckedChange;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.inject.Inject;

/**
 * @author Tom Koptel
 * @since 2.5
 */
@EViewGroup(R.layout.view_schedule_form)
public class ScheduleFormView extends LinearLayout implements DateDialogFragment.IcDateDialogClickListener,
        OutputFormatDialogFragment.OutputFormatClickListener, ValueInputDialogFragment.ValueDialogCallback,
        NumberDialogFragment.NumberDialogClickListener, RecurrenceTypeDialogFragment.RecurrenceTypeClickListener,
        IntervalUnitDialogFragment.IntervalUnitClickListener, CalendarMonthDialogFragment.MonthsSelectedListener,
        CalendarDayDialogFragment.DaysSelectedListener {

    public final static int JOB_NAME_CODE = 563;
    public final static int JOB_DESCRIPTION_CODE = 562;
    public final static int FILE_NAME_CODE = 251;
    public final static int OUTPUT_PATH_CODE = 515;
    public final static int REPEAT_INTERVAL_COUNT_CODE = 517;
    public final static int REPEAT_OCCURRENCE_COUNT_CODE = 518;
    public final static int START_DATE_CHANGED_CODE = 519;
    public final static int END_DATE_CHANGED_CODE = 520;
    public final static int DAYS_IN_MONTH_CODE = 521;
    public final static int MINUTES_CODE = 522;
    public final static int HOURS_CODE = 523;

    @Inject
    FragmentManager mFragmentManager;
    @Inject
    Fragment mParentFragment;
    @Inject
    ScheduleFormContract.EventListener mEventListener;

    @ViewById(R.id.scheduleName)
    TextView jobName;
    @ViewById(R.id.description)
    TextView description;
    @ViewById(R.id.fileName)
    TextView fileName;
    @ViewById(R.id.ic_boolean_title)
    TextView runImmediatelyTitle;
    @ViewById(R.id.ic_boolean)
    CheckBox runImmediately;
    @ViewById(R.id.scheduleDate)
    DateTimeView scheduleDate;
    @ViewById(R.id.outputFormat)
    TextView outputFormat;
    @ViewById(R.id.outputPath)
    TextView outputPath;

    @ViewById(R.id.recurrenceType)
    TextView recurrenceType;
    @ViewById(R.id.repeatInterval)
    TextView repeatInterval;
    @ViewById(R.id.repeatUnit)
    TextView repeatUnit;
    @ViewById(R.id.scheduleEndGroup)
    RadioGroup scheduleEndGroup;
    @ViewById(R.id.numberOfRunsControl)
    View numberOfRunsControl;
    @ViewById(R.id.numberOfRuns)
    TextView numberOfRuns;
    @ViewById(R.id.runUntilDateControl)
    DateTimeView runUntilDateControl;
    @ViewById(R.id.simpleRecurrenceForm)
    View simpleRecurrenceForm;

    @ViewById(R.id.calendarRecurrenceForm)
    View calendarRecurrenceForm;
    @ViewById(R.id.selectedMonths)
    TextView selectedMonths;
    @ViewById(R.id.selectedDaysInWeek)
    TextView selectedDaysInWeek;
    @ViewById(R.id.selectedDaysInMonth)
    TextView selectedDaysInMonth;
    @ViewById(R.id.selectedDaysInMonthHint)
    TextView selectedDaysInMonthHint;
    @ViewById(R.id.selectedHours)
    TextView selectedHours;
    @ViewById(R.id.selectedMinutes)
    TextView selectedMinutes;
    @ViewById(R.id.selectDaysControl)
    RadioGroup selectDaysControl;
    @ViewById(R.id.calendarEndDate)
    DateTimeView calendarEndDate;

    private JobFormViewBundle formBundle;
    private JobFormViewEntity form;

    public ScheduleFormView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void showForm(JobFormViewBundle bundle) {
        this.form = bundle.form();
        this.formBundle = bundle;
        update(form);
    }

    @Nullable
    public JobFormViewBundle provideForm() {
        if (formBundle == null) {
            return null;
        }
        return formBundle.newBuilder().form(form).build();
    }

    private void update(JobFormViewEntity form) {
        jobName.setText(form.jobName());
        fileName.setText(form.fileName());
        description.setText(provideDescription());

        scheduleDate.setDate(form.startDateAsCalendar());
        scheduleDate.setLabel(getString(R.string.sch_start_date));
        scheduleDate.enableClearButton(false);
        scheduleDate.setDateTimeClickListener(new ScheduleDateClickListener());

        runImmediatelyTitle.setText(getString(R.string.sch_run_immediately));
        runImmediatelyCheckChanged(!form.hasStartDate());

        outputFormat.setText(form.outputFormatsAsString());
        outputPath.setText(form.folderUri());

        updateRecurrenceForm(form.recurrence());
    }

    private String provideDescription() {
        String description = form.description();
        description = description == null ? getString(R.string.empty_text_place_holder) : description;
        return description;
    }

    private void updateRecurrenceForm(JobFormViewEntity.Recurrence recurrence) {
        recurrenceType.setText(recurrence.localizedLabel());

        if (recurrence instanceof NoneViewRecurrence) {
            handleNoneRecurrence();
        }
        if (recurrence instanceof SimpleViewRecurrence) {
            SimpleViewRecurrence simpleRecurrence = (SimpleViewRecurrence) recurrence;
            handleSimpleRecurrence(simpleRecurrence);
        }
        if (recurrence instanceof CalendarViewRecurrence) {
            CalendarViewRecurrence calendarRecurrence = (CalendarViewRecurrence) recurrence;
            handleCalendarRecurrence(calendarRecurrence);
        }
    }

    private void handleCalendarRecurrence(CalendarViewRecurrence calendarRecurrence) {
        simpleRecurrenceForm.setVisibility(GONE);
        calendarRecurrenceForm.setVisibility(VISIBLE);

        calendarEndDate.setDateTimeClickListener(new CalendarEndDateListener());
        calendarEndDate.setLabel(getString(R.string.sch_end_date));
        calendarEndDate.setPreview(getString(R.string.empty_text_place_holder));
        calendarEndDate.enableClearButton(false);
        if (calendarRecurrence.endDate() != null) {
            calendarEndDate.setDate(calendarRecurrence.endDateAsCalendar());
        }

        selectedMonths.setText(calendarRecurrence.monthsAsString());
        if (calendarRecurrence.daysInWeek() != null) {
            selectDaysControl.check(R.id.selectDays);
            selectedDaysInWeek.setText(calendarRecurrence.daysInWeekAsString());
        }
        if (calendarRecurrence.daysInMonth() != null) {
            selectDaysControl.check(R.id.selectDaysInMonth);
            selectedDaysInMonth.setText(calendarRecurrence.daysInMonth());
        }
        selectedHours.setText(calendarRecurrence.hours());
        selectedMinutes.setText(calendarRecurrence.minutes());
    }

    private void handleSimpleRecurrence(SimpleViewRecurrence recurrence) {
        calendarRecurrenceForm.setVisibility(GONE);
        simpleRecurrenceForm.setVisibility(VISIBLE);

        repeatInterval.setText(recurrence.intervalAsString());
        repeatUnit.setText(recurrence.unit().toString());

        runUntilDateControl.setDateTimeClickListener(new TriggerEndDateListener());
        runUntilDateControl.setLabel(getString(R.string.sch_end_date));
        runUntilDateControl.setPreview(getString(R.string.empty_text_place_holder));
        runUntilDateControl.enableClearButton(false);

        if (recurrence.runsIndefinitely()) {
            scheduleEndGroup.check(R.id.runsIndefinitelyControl);
        } else if (recurrence.runsByOccurrences()) {
            scheduleEndGroup.check(R.id.runsOccurrenceControl);
            numberOfRuns.setText(recurrence.occurrenceAsString());
        } else if (recurrence.runsTillDate()) {
            runUntilDateControl.setDate(recurrence.untilDateAsCalendar());
            scheduleEndGroup.check(R.id.runsUntilControl);
        }
    }

    @CheckedChange(R.id.runsIndefinitelyControl)
    void onIndefinitelyChecked(boolean checked) {
        if (!checked)
            return;
        numberOfRunsControl.setVisibility(GONE);
        runUntilDateControl.setVisibility(GONE);

        if (form != null) {
            setSimpleRecurrenceEndDate(null);
            handleOccurrenceCountNumberChange(-1);
        }
    }

    @CheckedChange(R.id.runsOccurrenceControl)
    void onOccurrenceChecked(boolean checked) {
        if (!checked)
            return;
        numberOfRunsControl.setVisibility(VISIBLE);
        runUntilDateControl.setVisibility(GONE);

        if (form != null) {
            String runs = numberOfRuns.getText().toString();
            int runsCount;
            try {
                runsCount = Integer.parseInt(runs);
            } catch (NumberFormatException ex) {
                runsCount = 1;
            }
            setSimpleRecurrenceEndDate(null);
            handleOccurrenceCountNumberChange(runsCount);
            updateNumberOfRuns();
        }
    }

    @CheckedChange(R.id.runsUntilControl)
    void onUntilChecked(boolean checked) {
        if (!checked)
            return;
        numberOfRunsControl.setVisibility(GONE);
        runUntilDateControl.setVisibility(VISIBLE);

        if (form != null) {
            Calendar untilDate = runUntilDateControl.getDate();
            setSimpleRecurrenceEndDate(untilDate);
            updateRunUntilDate();
            handleOccurrenceCountNumberChange(-1);
        }
    }

    @CheckedChange(R.id.selectDays)
    void selectDays(boolean checked) {
        if (!checked)
            return;
        selectedDaysInWeek.setVisibility(VISIBLE);
        selectedDaysInMonth.setVisibility(GONE);
        selectedDaysInMonthHint.setVisibility(GONE);

        if (form != null) {
            CalendarViewRecurrence recurrence = (CalendarViewRecurrence) selectedDaysInWeek.getTag();
            if (recurrence != null) {
                updateDaysInWeek(recurrence.daysInWeek());
                updateDaysInWeekView(recurrence);
            }
            updateDaysInMonth(null);
        }
    }

    @CheckedChange(R.id.selectDaysInMonth)
    void selectDaysInMonth(boolean checked) {
        if (!checked)
            return;
        selectedDaysInWeek.setVisibility(GONE);
        selectedDaysInMonth.setVisibility(VISIBLE);
        selectedDaysInMonthHint.setVisibility(VISIBLE);

        if (form != null) {
            String daysInMonth = selectedDaysInMonth.getText().toString();
            String emptyHolder = getString(R.string.empty_text_place_holder);
            if (!emptyHolder.equals(daysInMonth)) {
                daysInMonth = TextUtils.isEmpty(daysInMonth) ? null : daysInMonth;

                updateDaysInMonth(daysInMonth);
                updateDaysInMonthView(getCalendarRecurrence());
            }
            updateDaysInWeek(Collections.<CalendarViewRecurrence.Day>emptyList());
        }
    }

    private void handleNoneRecurrence() {
        simpleRecurrenceForm.setVisibility(GONE);
        calendarRecurrenceForm.setVisibility(GONE);
    }

    private String getString(@StringRes int id) {
        return getContext().getResources().getString(id);
    }

    @Click(R.id.descriptionContainer)
    protected void descriptionContainer() {
        String description = form.description();
        description = description == null ? "" : description;
        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sch_description))
                .setValue(description).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(JOB_DESCRIPTION_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.runImmediately)
    protected void runImmediatelyClicked() {
        runImmediately.performClick();
    }

    @Click(R.id.selectedDaysInMonth)
    protected void selectedDaysInMonthClick() {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        String value = recurrence.daysInMonth();
        value = value == null ? "" : value;

        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sr_dates_in_month))
                .setValue(value).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(DAYS_IN_MONTH_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.selectHours)
    protected void selectHoursInMonthClick() {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sr_hours))
                .setValue(recurrence.hours()).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(HOURS_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.selectMinutes)
    protected void selectMinutesInMonthClick() {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sr_minutes))
                .setValue(recurrence.minutes()).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(MINUTES_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.scheduleNameContainer)
    protected void scheduleNameClick() {
        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sch_job_name))
                .setValue(jobName.getText().toString()).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(JOB_NAME_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.fileNameContainer)
    protected void fileNameClick() {
        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sch_file_name))
                .setValue(fileName.getText().toString()).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(FILE_NAME_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.outputFormatContainer)
    protected void selectOutputFormat() {
        OutputFormatDialogFragment.createBuilder(mFragmentManager).setSelected(form.outputFormats())
                .setFormats(formBundle.allFormats()).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.outputPathContainer)
    protected void outputPathClick() {
        ValueInputDialogFragment.createBuilder(mFragmentManager).setLabel(getString(R.string.sch_destination))
                .setValue(outputPath.getText().toString()).setRequired(true).setCancelableOnTouchOutside(true)
                .setRequestCode(OUTPUT_PATH_CODE).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.recurrence)
    protected void selectRecurrence() {
        RecurrenceTypeDialogFragment.createBuilder(mFragmentManager).setRecurrence(form.recurrence())
                .setRecurrences(formBundle.allRecurrences()).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.repeatInterval)
    protected void repeatIntervalNumberClicked() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();

        NumberDialogFragment.createBuilder(mFragmentManager).setTitle(R.string.sr_repeat_every)
                .setValue(recurrence.interval()).setRequestCode(REPEAT_INTERVAL_COUNT_CODE)
                .setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.numberOfRunsControl)
    protected void repeatOccurrenceNumberClicked() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();

        Integer occurrence = recurrence.occurrence();

        NumberDialogFragment.PageDialogFragmentBuilder builder = NumberDialogFragment
                .createBuilder(mFragmentManager).setTitle(R.string.sr_number_of_runs);
        if (occurrence != null) {
            builder.setValue(occurrence);
        }
        builder.setRequestCode(REPEAT_OCCURRENCE_COUNT_CODE);
        builder.setTargetFragment(mParentFragment);
        builder.show();
    }

    @Click(R.id.repeatUnit)
    protected void intervalUnitClicked() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();

        IntervalUnitDialogFragment.createBuilder(mFragmentManager).setUnit(recurrence.unit())
                .setUnits(formBundle.allIntervalUnits()).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.selectMonths)
    protected void selectMonthsClicked() {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        CalendarMonthDialogFragment.createBuilder(mFragmentManager).setMonths(formBundle.allMonths())
                .setSelected(recurrence.months()).setTargetFragment(mParentFragment).show();
    }

    @Click(R.id.selectedDaysInWeek)
    protected void selectDaysInWeekClicked() {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        List<CalendarViewRecurrence.Day> days = recurrence.daysInWeek();
        if (days == null) {
            recurrence = (CalendarViewRecurrence) selectedDaysInWeek.getTag();
            if (recurrence != null) {
                days = recurrence.daysInWeek();
            }
        }
        days = days == null ? Collections.<CalendarViewRecurrence.Day>emptyList() : days;

        CalendarDayDialogFragment.createBuilder(mFragmentManager).setDays(formBundle.allDays()).setSelected(days)
                .setTargetFragment(mParentFragment).show();
    }

    @CheckedChange(R.id.ic_boolean)
    protected void runImmediatelyCheckChanged(boolean checked) {
        runImmediately.setChecked(checked);
        scheduleDate.setVisibility(checked ? View.GONE : View.VISIBLE);

        if (form != null) {
            Date date = checked ? null : scheduleDate.getDate().getTime();
            form = form.newBuilder().startDate(date).build();
        }
    }

    @Override
    public void onDateSelected(Calendar date, int requestCode, Object... metadata) {
        switch (requestCode) {
        case START_DATE_CHANGED_CODE:
            updateStartDate(date);
            break;
        case END_DATE_CHANGED_CODE:
            updateEndDate(date);
            break;
        }
    }

    private void updateStartDate(Calendar startDate) {
        if (startDate == null) {
            setStartDate(null);
            return;
        }

        if (startDate.getTimeInMillis() < new Date().getTime()) {
            Toast.makeText(getContext(), getString(R.string.error_schedule_start_date_in_the_past),
                    Toast.LENGTH_SHORT).show();
        } else {
            setStartDate(startDate);
        }
    }

    private void setStartDate(Calendar startDate) {
        form = form.newBuilder().startDate(startDate.getTime()).build();
        scheduleDate.setDate(startDate);
    }

    private void updateEndDate(Calendar endDate) {
        if (endDate == null) {
            setEndDate(null);
            return;
        }

        if (endDate.getTimeInMillis() < new Date().getTime()) {
            Toast.makeText(getContext(), getString(R.string.error_schedule_end_date_in_the_past),
                    Toast.LENGTH_SHORT).show();
        } else {
            setEndDate(endDate);
        }
    }

    private void setEndDate(Calendar endDate) {
        if (form.recurrence() instanceof SimpleViewRecurrence) {
            setSimpleRecurrenceEndDate(endDate);
            updateRunUntilDate();
        }
        if (form.recurrence() instanceof CalendarViewRecurrence) {
            setCalendarRecurrenceEndDate(endDate);
        }
    }

    private void setCalendarRecurrenceEndDate(@Nullable Calendar date) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();

        Date endDate = date == null ? null : date.getTime();
        CalendarViewRecurrence modifiedRecurrence = recurrence.newBuilder().endDate(endDate).build();
        updateRecurrence(modifiedRecurrence);
        calendarEndDate.setDate(date);
    }

    private void setSimpleRecurrenceEndDate(@Nullable Calendar date) {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();

        Date endDate = date == null ? null : date.getTime();
        SimpleViewRecurrence modifiedRecurrence = recurrence.newBuilder().untilDate(endDate).build();
        updateRecurrence(modifiedRecurrence);
    }

    private void updateRunUntilDate() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        runUntilDateControl.setDate(recurrence.untilDateAsCalendar());
    }

    @Override
    public void onTextValueEntered(int requestCode, String name) {
        switch (requestCode) {
        case JOB_DESCRIPTION_CODE:
            updateJobDescription(name);
            break;
        case JOB_NAME_CODE:
            updateJobName(name);
            break;
        case FILE_NAME_CODE:
            updateFileName(name);
            break;
        case OUTPUT_PATH_CODE:
            updateOutputPath(name);
            break;
        case DAYS_IN_MONTH_CODE:
            updateDaysInMonth(name);
            updateDaysInMonthView(getCalendarRecurrence());
            break;
        case MINUTES_CODE:
            updateMinutes(name);
            break;
        case HOURS_CODE:
            updateHours(name);
            break;
        }
    }

    private void updateOutputPath(String path) {
        form = form.newBuilder().folderUri(path).build();
        outputPath.setText(path);
    }

    private void updateFileName(String fileName) {
        form = form.newBuilder().fileName(fileName).build();
        this.fileName.setText(fileName);
    }

    private void updateJobDescription(String description) {
        form = form.newBuilder().description(description).build();
        this.description.setText(description);
    }

    private void updateJobName(String name) {
        form = form.newBuilder().jobName(name).build();
        jobName.setText(name);
    }

    private void updateDaysInMonth(String days) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();
        CalendarViewRecurrence updatedRecurrence = recurrence.newBuilder().daysInMonth(days).build();
        updateRecurrence(updatedRecurrence);
    }

    private void updateDaysInMonthView(CalendarViewRecurrence recurrence) {
        selectedDaysInMonth.setText(recurrence.daysInMonth());
    }

    private void updateMinutes(String minutes) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();
        CalendarViewRecurrence updatedRecurrence = recurrence.newBuilder().minutes(minutes).build();
        updateRecurrence(updatedRecurrence);
        selectedMinutes.setText(minutes);
    }

    private void updateHours(String hours) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();
        CalendarViewRecurrence updatedRecurrence = recurrence.newBuilder().hours(hours).build();
        updateRecurrence(updatedRecurrence);
        selectedHours.setText(hours);
    }

    private void updateRecurrence(JobFormViewEntity.Recurrence recurrence) {
        form = form.newBuilder().recurrence(recurrence).build();
    }

    @NonNull
    private CalendarViewRecurrence getCalendarRecurrence() {
        return (CalendarViewRecurrence) form.recurrence();
    }

    @Override
    public void onOutputFormatSelected(List<JobFormViewEntity.OutputFormat> newFormats) {
        form = form.newBuilder().outputFormats(newFormats).build();
        outputFormat.setText(form.outputFormatsAsString());
    }

    @Override
    public void onRecurrenceSelected(JobFormViewEntity.Recurrence recurrence) {
        updateRecurrence(recurrence);
        updateRecurrenceForm(recurrence);
    }

    @Override
    public void onNumberSubmit(int number, int requestCode) {
        switch (requestCode) {
        case REPEAT_INTERVAL_COUNT_CODE:
            handleRepeatDayNumberChange(number);
            updateRepeatInterval();
            break;
        case REPEAT_OCCURRENCE_COUNT_CODE:
            handleOccurrenceCountNumberChange(number);
            updateNumberOfRuns();
            break;
        }
    }

    private void handleOccurrenceCountNumberChange(int occurrenceCount) {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        SimpleViewRecurrence modifiedRecurrence = recurrence.newBuilder().occurrence(occurrenceCount).build();
        form = form.newBuilder().recurrence(modifiedRecurrence).build();
    }

    private void updateRepeatInterval() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        repeatInterval.setText(recurrence.intervalAsString());
    }

    private void handleRepeatDayNumberChange(int intervalCount) {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        SimpleViewRecurrence modifiedRecurrence = recurrence.newBuilder().interval(intervalCount).build();
        form = form.newBuilder().recurrence(modifiedRecurrence).build();
    }

    private void updateNumberOfRuns() {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        numberOfRuns.setText(recurrence.occurrenceAsString());
    }

    @Override
    public void onUnitSelected(SimpleViewRecurrence.Unit unit) {
        SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
        SimpleViewRecurrence modifiedRecurrence = recurrence.newBuilder().unit(unit).build();
        form = form.newBuilder().recurrence(modifiedRecurrence).build();

        repeatUnit.setText(unit.toString());
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        if (formBundle == null) {
            mEventListener.onViewReady();
        } else {
            showForm(formBundle);
        }
    }

    @Override
    public void onMonthsSelected(List<CalendarViewRecurrence.Month> months) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();
        CalendarViewRecurrence updatedRecurrence = recurrence.newBuilder().months(months).build();
        updateRecurrence(updatedRecurrence);
        selectedMonths.setText(updatedRecurrence.monthsAsString());
    }

    @Override
    public void onDaysSelected(List<CalendarViewRecurrence.Day> selectedDays) {
        updateDaysInWeek(selectedDays);
        updateDaysInWeekView(getCalendarRecurrence());
    }

    private void updateDaysInWeek(List<CalendarViewRecurrence.Day> selectedDays) {
        CalendarViewRecurrence recurrence = getCalendarRecurrence();
        CalendarViewRecurrence updatedRecurrence = recurrence.newBuilder().daysInWeek(selectedDays).build();
        updateRecurrence(updatedRecurrence);
    }

    private void updateDaysInWeekView(CalendarViewRecurrence recurrence) {
        selectedDaysInWeek.setTag(recurrence);
        selectedDaysInWeek.setText(recurrence.daysInWeekAsString());
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable superState = super.onSaveInstanceState();
        SavedState saveState = new SavedState(superState);
        saveState.formBundle = formBundle.newBuilder().form(form).build();
        saveState.weekInDays = (CalendarViewRecurrence) selectedDaysInWeek.getTag();
        return saveState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        boolean canDelegate = (state instanceof SavedState);
        if (canDelegate) {
            SavedState ss = (SavedState) state;
            formBundle = ss.formBundle;
            selectedDaysInWeek.setTag(ss.weekInDays);
            super.onRestoreInstanceState(ss.getSuperState());
        } else {
            super.onRestoreInstanceState(state);
        }
    }

    public boolean validate() {
        Date date = form.startDate();
        if (date != null) {
            long startDate = date.getTime();
            long currentDate = new Date().getTime();
            if (startDate < currentDate) {
                Toast.makeText(getContext(), getString(R.string.error_schedule_start_date_in_the_past),
                        Toast.LENGTH_SHORT).show();
                return false;
            }
        }
        return true;
    }

    private static class SavedState extends View.BaseSavedState {
        JobFormViewBundle formBundle;
        CalendarViewRecurrence weekInDays;

        public SavedState(Parcel source) {
            super(source);
            formBundle = source.readParcelable(JobFormViewBundle.class.getClassLoader());
            weekInDays = source.readParcelable(CalendarViewRecurrence.class.getClassLoader());
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeParcelable(formBundle, 0);
            dest.writeParcelable(weekInDays, 0);
        }

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }

    private class ScheduleDateClickListener implements DateTimeView.DateTimeClickListener {
        @Override
        public void onDateClick(int position) {
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(form.startDateAsCalendar()).setType(DateDialogFragment.DATE)
                    .setTargetFragment(mParentFragment).setRequestCode(START_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onTimeClick(int position) {
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(form.startDateAsCalendar()).setType(DateDialogFragment.TIME)
                    .setTargetFragment(mParentFragment).setRequestCode(START_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onClear(int position) {
            form = form.newBuilder().startDate(null).build();
            scheduleDate.setDate(null);
        }
    }

    private class TriggerEndDateListener implements DateTimeView.DateTimeClickListener {
        @Override
        public void onDateClick(int position) {
            SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(recurrence.untilDateAsCalendar()).setType(DateDialogFragment.DATE)
                    .setTargetFragment(mParentFragment).setRequestCode(END_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onTimeClick(int position) {
            SimpleViewRecurrence recurrence = (SimpleViewRecurrence) form.recurrence();
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(recurrence.untilDateAsCalendar()).setType(DateDialogFragment.TIME)
                    .setTargetFragment(mParentFragment).setRequestCode(END_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onClear(int position) {
            updateEndDate(null);
        }
    }

    private class CalendarEndDateListener implements DateTimeView.DateTimeClickListener {
        @Override
        public void onDateClick(int position) {
            CalendarViewRecurrence recurrence = getCalendarRecurrence();
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(recurrence.endDateAsCalendar()).setType(DateDialogFragment.DATE)
                    .setTargetFragment(mParentFragment).setRequestCode(END_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onTimeClick(int position) {
            CalendarViewRecurrence recurrence = getCalendarRecurrence();
            DateDialogFragment.createBuilder(mFragmentManager).setInputControlId(null)
                    .setDate(recurrence.endDateAsCalendar()).setType(DateDialogFragment.TIME)
                    .setTargetFragment(mParentFragment).setRequestCode(END_DATE_CHANGED_CODE).show();
        }

        @Override
        public void onClear(int position) {
            updateEndDate(null);
        }
    }
}