private void editRecur(Recur recur) {
   editStartDate(recur.startDate);
   RecurInterval interval = recur.interval;
   SpinnerAdapter adapter = sInterval.getAdapter();
   int count = adapter.getCount();
   for (int i = 0; i < count; i++) {
     SpinnerItem item = (SpinnerItem) adapter.getItem(i);
     if (interval == RecurInterval.valueOf(item.value)) {
       sInterval.setSelection(i);
       break;
     }
   }
   View v = selectInterval(interval);
   switch (interval) {
     case EVERY_X_DAY:
       editEveryXDay(v, recur);
       break;
     case WEEKLY:
       editWeekly(v, recur);
       break;
     case SEMI_MONTHLY:
       editSemiMonthly(v, recur);
       break;
   }
   RecurPeriod period = recur.period;
   sPeriod.setSelection(period.ordinal());
   v = selectPeriod(period);
   switch (period) {
     case EXACTLY_TIMES:
       editExactlyTimes(v, recur.periodParam);
       break;
     case STOPS_ON_DATE:
       editStopsOnDate(v, recur.periodParam);
       break;
   }
 }
public class RecurActivity extends Activity {

  public static final String EXTRA_RECUR = "recur";

  private static final RecurPeriod[] periods = RecurPeriod.values();

  private Spinner sInterval;
  private Spinner sPeriod;
  private LinearLayout layoutInterval;
  private LinearLayout layoutRecur;
  private Button bStartDate;

  private final Calendar startDate = Calendar.getInstance();
  private final Calendar stopsOnDate = Calendar.getInstance();

  private DateFormat df;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_LEFT_ICON);
    setContentView(R.layout.recur);
    setFeatureDrawableResource(Window.FEATURE_LEFT_ICON, R.drawable.ic_dialog_time);

    df = DateUtils.getLongDateFormat(this);

    stopsOnDate.add(Calendar.YEAR, 1);

    sInterval = (Spinner) findViewById(R.id.intervalSpinner);
    sPeriod = (Spinner) findViewById(R.id.recurSpinner);
    layoutInterval = (LinearLayout) findViewById(R.id.layoutInterval);
    layoutRecur = (LinearLayout) findViewById(R.id.recurInterval);

    bStartDate = (Button) findViewById(R.id.bStartDate);
    bStartDate.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(final View v) {
            final Calendar c = startDate;
            DatePickerDialog d =
                new DatePickerDialog(
                    RecurActivity.this,
                    new DatePickerDialog.OnDateSetListener() {
                      @Override
                      public void onDateSet(
                          DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                        c.set(Calendar.YEAR, year);
                        c.set(Calendar.MONTH, monthOfYear);
                        c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                        DateUtils.startOfDay(c);
                        editStartDate(c.getTimeInMillis());
                      }
                    },
                    c.get(Calendar.YEAR),
                    c.get(Calendar.MONTH),
                    c.get(Calendar.DAY_OF_MONTH));
            d.show();
          }
        });

    addSpinnerItems(
        sInterval,
        new RecurInterval[] {RecurInterval.NO_RECUR, RecurInterval.WEEKLY, RecurInterval.MONTHLY});
    addSpinnerItems(sPeriod, periods);

    LayoutInflater inflater = getLayoutInflater();
    // addLayouts(inflater, layoutInterval, intervals);
    addLayouts(inflater, layoutRecur, periods);

    Recur recur = RecurUtils.createDefaultRecur();
    Intent intent = getIntent();
    if (intent != null) {
      String extra = intent.getStringExtra(EXTRA_RECUR);
      if (extra != null) {
        recur = RecurUtils.createFromExtraString(extra);
      }
    }
    editRecur(recur);

    sInterval.setOnItemSelectedListener(
        new OnItemSelectedListener() {
          @Override
          public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            RecurInterval interval = getRecurInterval(sInterval.getSelectedItem());
            selectInterval(interval);
          }

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

    sPeriod.setOnItemSelectedListener(
        new OnItemSelectedListener() {
          @Override
          public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            RecurPeriod period = periods[position];
            selectPeriod(period);
          }

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

    Button bOk = (Button) findViewById(R.id.bOK);
    bOk.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View view) {
            RecurInterval interval = getRecurInterval(sInterval.getSelectedItem());
            RecurPeriod period = periods[sPeriod.getSelectedItemPosition()];
            Recur r = RecurUtils.createRecur(interval);
            r.startDate = startDate.getTimeInMillis();
            r.period = period;
            if (updateInterval(r) && updatePeriod(r)) {
              Intent data = new Intent();
              data.putExtra(EXTRA_RECUR, r.toString());
              setResult(RESULT_OK, data);
              finish();
            }
          }
        });

    Button bCancel = (Button) findViewById(R.id.bCancel);
    bCancel.setOnClickListener(
        new OnClickListener() {
          @Override
          public void onClick(View view) {
            setResult(RESULT_CANCELED, null);
            finish();
          }
        });
  }

  private static class SpinnerItem {
    public final String title;
    public final String value;

    public SpinnerItem(String title, String value) {
      super();
      this.title = title;
      this.value = value;
    }

    @Override
    public String toString() {
      return title;
    }
  }

  private void addSpinnerItems(Spinner spinner, LocalizableEnum[] a) {
    int length = a.length;
    SpinnerItem[] items = new SpinnerItem[length];
    for (int i = 0; i < length; i++) {
      LocalizableEnum x = a[i];
      String title = getString(x.getTitleId());
      String value = x.name();
      items[i] = new SpinnerItem(title, value);
    }
    ArrayAdapter<SpinnerItem> adapter =
        new ArrayAdapter<SpinnerItem>(this, android.R.layout.simple_spinner_item, items);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);
  }

  protected RecurInterval getRecurInterval(Object item) {
    return RecurInterval.valueOf(((SpinnerItem) item).value);
  }

  protected boolean updateInterval(Recur r) {
    RecurInterval interval = r.interval;
    View v = selectInterval(interval);
    switch (interval) {
      case EVERY_X_DAY:
        return updateEveryXDay(v, r);
      case WEEKLY:
        return updateWeekly(v, r);
      case SEMI_MONTHLY:
        return updateSemiMonthly(v, r);
    }
    return true;
  }

  protected boolean updatePeriod(Recur r) {
    RecurPeriod period = r.period;
    View v = selectPeriod(period);
    switch (period) {
      case EXACTLY_TIMES:
        return updateExactlyTimes(v, r);
      case STOPS_ON_DATE:
        return updateStopsOnDate(v, r);
    }
    return true;
  }

  private void addLayouts(LayoutInflater inflater, LinearLayout layout, Layoutable[] items) {
    for (Layoutable i : items) {
      int layoutId = i.getLayoutId();
      if (layoutId != 0) {
        final View v = inflater.inflate(layoutId, null);
        v.setTag(i);
        v.setVisibility(View.INVISIBLE);
        if (i == RecurPeriod.STOPS_ON_DATE) {
          Button b = (Button) v.findViewById(R.id.bStopsOnDate);
          final Calendar c = this.stopsOnDate;
          editStopsOnDate(v, c.getTimeInMillis());
          b.setOnClickListener(
              new OnClickListener() {
                @Override
                public void onClick(final View view) {
                  DatePickerDialog d =
                      new DatePickerDialog(
                          RecurActivity.this,
                          new DatePickerDialog.OnDateSetListener() {
                            @Override
                            public void onDateSet(
                                DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                              c.set(Calendar.YEAR, year);
                              c.set(Calendar.MONTH, monthOfYear);
                              c.set(Calendar.DAY_OF_MONTH, dayOfMonth);
                              DateUtils.endOfDay(c);
                              editStopsOnDate(v, c.getTimeInMillis());
                            }
                          },
                          c.get(Calendar.YEAR),
                          c.get(Calendar.MONTH),
                          c.get(Calendar.DAY_OF_MONTH));
                  d.show();
                }
              });
        }
        layout.addView(v, LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
      }
    }
  }

  private void editRecur(Recur recur) {
    editStartDate(recur.startDate);
    RecurInterval interval = recur.interval;
    SpinnerAdapter adapter = sInterval.getAdapter();
    int count = adapter.getCount();
    for (int i = 0; i < count; i++) {
      SpinnerItem item = (SpinnerItem) adapter.getItem(i);
      if (interval == RecurInterval.valueOf(item.value)) {
        sInterval.setSelection(i);
        break;
      }
    }
    View v = selectInterval(interval);
    switch (interval) {
      case EVERY_X_DAY:
        editEveryXDay(v, recur);
        break;
      case WEEKLY:
        editWeekly(v, recur);
        break;
      case SEMI_MONTHLY:
        editSemiMonthly(v, recur);
        break;
    }
    RecurPeriod period = recur.period;
    sPeriod.setSelection(period.ordinal());
    v = selectPeriod(period);
    switch (period) {
      case EXACTLY_TIMES:
        editExactlyTimes(v, recur.periodParam);
        break;
      case STOPS_ON_DATE:
        editStopsOnDate(v, recur.periodParam);
        break;
    }
  }

  private void editEveryXDay(View v, Recur recur) {
    EveryXDay x = (EveryXDay) recur;
    EditText t = (EditText) v.findViewById(R.id.edEveryXDays);
    t.setText(String.valueOf(x.days));
  }

  private void editWeekly(View v, Recur recur) {
    return;
  }

  private void editSemiMonthly(View v, Recur recur) {
    SemiMonthly sm = (SemiMonthly) recur;
    EditText t1 = (EditText) v.findViewById(R.id.edFirstDay);
    t1.setText(String.valueOf(sm.firstDay));
    EditText t2 = (EditText) v.findViewById(R.id.edSecondDay);
    t2.setText(String.valueOf(sm.secondDay));
  }

  private boolean updateEveryXDay(View v, Recur r) {
    EveryXDay x = (EveryXDay) r;
    EditText t = (EditText) v.findViewById(R.id.edEveryXDays);
    if (Utils.isEmpty(t)) {
      showError(t, R.string.recur_error_specify_days);
      return false;
    }
    x.days = Integer.parseInt(Utils.text(t));
    return true;
  }

  private void showError(EditText t, int messageId) {
    t.setError(getString(messageId));
  }

  private boolean updateWeekly(View v, Recur r) {
    Weekly w = (Weekly) r;
    int i = startDate.get(Calendar.DAY_OF_WEEK);
    DayOfWeek[] days = DayOfWeek.values();
    for (DayOfWeek d : days) {
      w.unset(d);
    }
    w.set(days[i - 1]);
    return true;
  }

  private boolean updateSemiMonthly(View v, Recur r) {
    SemiMonthly sm = (SemiMonthly) r;
    EditText t1 = (EditText) v.findViewById(R.id.edFirstDay);
    if (Utils.isEmpty(t1)) {
      showError(t1, R.string.recur_error_specify_first_day);
      return false;
    }
    sm.firstDay = Integer.parseInt(Utils.text(t1));
    EditText t2 = (EditText) v.findViewById(R.id.edSecondDay);
    if (Utils.isEmpty(t2)) {
      showError(t2, R.string.recur_error_specify_second_day);
      return false;
    }
    sm.secondDay = Integer.parseInt(Utils.text(t2));
    return true;
  }

  private void editExactlyTimes(View v, long times) {
    EditText e = (EditText) v.findViewById(R.id.edTimes);
    e.setText(times > 0 ? String.valueOf(times) : "1");
  }

  private void editStartDate(long date) {
    Calendar c = startDate;
    c.setTimeInMillis(date);
    bStartDate.setText(df.format(c.getTime()));
  }

  private void editStopsOnDate(View v, long date) {
    Calendar c = stopsOnDate;
    c.setTimeInMillis(date);
    Button b = (Button) v.findViewById(R.id.bStopsOnDate);
    b.setText(df.format(c.getTime()));
  }

  private boolean updateExactlyTimes(View v, Recur r) {
    EditText e = (EditText) v.findViewById(R.id.edTimes);
    if (Utils.isEmpty(e)) {
      showError(e, R.string.recur_error_specify_times);
      return false;
    }
    r.periodParam = Long.parseLong(Utils.text(e));
    return true;
  }

  private boolean updateStopsOnDate(View v, Recur r) {
    r.periodParam = stopsOnDate.getTimeInMillis();
    return true;
  }

  protected View selectInterval(RecurInterval interval) {
    if (interval == RecurInterval.NO_RECUR) {
      sPeriod.setSelection(RecurPeriod.STOPS_ON_DATE.ordinal());
      sPeriod.setEnabled(false);
    } else {
      sPeriod.setEnabled(true);
    }
    return selectInLayout(layoutInterval, interval);
  }

  protected View selectPeriod(RecurPeriod period) {
    return selectInLayout(layoutRecur, period);
  }

  private View selectInLayout(LinearLayout layout, Object tag) {
    View selected = null;
    int count = layout.getChildCount();
    for (int i = 0; i < count; i++) {
      View v = layout.getChildAt(i);
      if (tag == v.getTag()) {
        selected = v;
      } else {
        v.setVisibility(View.GONE);
      }
    }
    if (selected != null) {
      selected.setVisibility(View.VISIBLE);
    }
    return selected;
  }

  @Override
  protected void onPause() {
    super.onPause();
    PinProtection.lock(this);
  }

  @Override
  protected void onResume() {
    super.onResume();
    PinProtection.unlock(this);
  }
}