content: /*
   * Copyright (C) 2013 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package com.android.datetimepicker.date;
  
  import android.animation.ObjectAnimator;
  import android.app.Activity;
  import android.app.DialogFragment;
  import android.content.res.Resources;
  import android.os.Bundle;
  import android.text.format.DateUtils;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.view.ViewGroup;
  import android.view.Window;
  import android.view.WindowManager;
  import android.view.animation.AlphaAnimation;
  import android.view.animation.Animation;
  import android.widget.Button;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.android.datetimepicker.HapticFeedbackController;
  import com.android.datetimepicker.R;
  import com.android.datetimepicker.Utils;
  import com.android.datetimepicker.date.MonthAdapter.CalendarDay;
  
  import java.text.SimpleDateFormat;
  import java.util.Calendar;
  import java.util.HashSet;
  import java.util.Iterator;
  import java.util.Locale;
  
  /**
   * Dialog allowing users to select a date.
   *
   * @deprecated Use {@link android.app.DatePickerDialog}.
   */
  @Deprecated
  public class DatePickerDialog extends DialogFragment implements
          OnClickListener, DatePickerController {
  
      private static final String TAG = "DatePickerDialog";
  
      private static final int UNINITIALIZED = -1;
      private static final int MONTH_AND_DAY_VIEW = 0;
      private static final int YEAR_VIEW = 1;
  
      private static final String KEY_SELECTED_YEAR = "year";
      private static final String KEY_SELECTED_MONTH = "month";
      private static final String KEY_SELECTED_DAY = "day";
      private static final String KEY_LIST_POSITION = "list_position";
      private static final String KEY_WEEK_START = "week_start";
      private static final String KEY_YEAR_START = "year_start";
      private static final String KEY_YEAR_END = "year_end";
      private static final String KEY_CURRENT_VIEW = "current_view";
      private static final String KEY_LIST_POSITION_OFFSET = "list_position_offset";
  
      private static final int DEFAULT_START_YEAR = 1900;
      private static final int DEFAULT_END_YEAR = 2100;
  
      private static final int ANIMATION_DURATION = 300;
      private static final int ANIMATION_DELAY = 500;
  
      private static SimpleDateFormat YEAR_FORMAT = new SimpleDateFormat("yyyy", Locale.getDefault());
      private static SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("dd", Locale.getDefault());
  
      private final Calendar mCalendar = Calendar.getInstance();
      private OnDateSetListener mCallBack;
      private HashSet<OnDateChangedListener> mListeners = new HashSet<OnDateChangedListener>();
  
      private AccessibleDateAnimator mAnimator;
  
      private TextView mDayOfWeekView;
      private LinearLayout mMonthAndDayView;
      private TextView mSelectedMonthTextView;
      private TextView mSelectedDayTextView;
      private TextView mYearView;
      private DayPickerView mDayPickerView;
      private YearPickerView mYearPickerView;
      private Button mDoneButton;
  
      private int mCurrentView = UNINITIALIZED;
  
      private int mWeekStart = mCalendar.getFirstDayOfWeek();
      private int mMinYear = DEFAULT_START_YEAR;
      private int mMaxYear = DEFAULT_END_YEAR;
      private Calendar mMinDate;
      private Calendar mMaxDate;
  
      private HapticFeedbackController mHapticFeedbackController;
  
      private boolean mDelayAnimation = true;
  
      // Accessibility strings.
      private String mDayPickerDescription;
      private String mSelectDay;
      private String mYearPickerDescription;
      private String mSelectYear;
  
      /**
       * The callback used to indicate the user is done filling in the date.
       */
      public interface OnDateSetListener {
  
          /**
           * @param view The view associated with this listener.
           * @param year The year that was set.
           * @param monthOfYear The month that was set (0-11) for compatibility
           *            with {@link java.util.Calendar}.
           * @param dayOfMonth The day of the month that was set.
           */
          void onDateSet(DatePickerDialog dialog, int year, int monthOfYear, int dayOfMonth);
      }
  
      /**
       * The callback used to notify other date picker components of a change in selected date.
       */
      public interface OnDateChangedListener {
  
          public void onDateChanged();
      }
  
  
      public DatePickerDialog() {
          // Empty constructor required for dialog fragment.
      }
  
      /**
       * @param callBack How the parent is notified that the date is set.
       * @param year The initial year of the dialog.
       * @param monthOfYear The initial month of the dialog.
       * @param dayOfMonth The initial day of the dialog.
       */
      public static DatePickerDialog newInstance(OnDateSetListener callBack, int year,
              int monthOfYear,
              int dayOfMonth) {
          DatePickerDialog ret = new DatePickerDialog();
          ret.initialize(callBack, year, monthOfYear, dayOfMonth);
          return ret;
      }
  
      public void initialize(OnDateSetListener callBack, int year, int monthOfYear, int dayOfMonth) {
          mCallBack = callBack;
          mCalendar.set(Calendar.YEAR, year);
          mCalendar.set(Calendar.MONTH, monthOfYear);
          mCalendar.set(Calendar.DAY_OF_MONTH, dayOfMonth);
      }
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          final Activity activity = getActivity();
          activity.getWindow().setSoftInputMode(
                  WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
          if (savedInstanceState != null) {
              mCalendar.set(Calendar.YEAR, savedInstanceState.getInt(KEY_SELECTED_YEAR));
              mCalendar.set(Calendar.MONTH, savedInstanceState.getInt(KEY_SELECTED_MONTH));
              mCalendar.set(Calendar.DAY_OF_MONTH, savedInstanceState.getInt(KEY_SELECTED_DAY));
          }
      }
  
      @Override
      public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
          outState.putInt(KEY_SELECTED_YEAR, mCalendar.get(Calendar.YEAR));
          outState.putInt(KEY_SELECTED_MONTH, mCalendar.get(Calendar.MONTH));
          outState.putInt(KEY_SELECTED_DAY, mCalendar.get(Calendar.DAY_OF_MONTH));
          outState.putInt(KEY_WEEK_START, mWeekStart);
          outState.putInt(KEY_YEAR_START, mMinYear);
          outState.putInt(KEY_YEAR_END, mMaxYear);
          outState.putInt(KEY_CURRENT_VIEW, mCurrentView);
          int listPosition = -1;
          if (mCurrentView == MONTH_AND_DAY_VIEW) {
              listPosition = mDayPickerView.getMostVisiblePosition();
          } else if (mCurrentView == YEAR_VIEW) {
              listPosition = mYearPickerView.getFirstVisiblePosition();
              outState.putInt(KEY_LIST_POSITION_OFFSET, mYearPickerView.getFirstPositionOffset());
          }
          outState.putInt(KEY_LIST_POSITION, listPosition);
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
              Bundle savedInstanceState) {
          Log.d(TAG, "onCreateView: ");
          getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
  
          View view = inflater.inflate(R.layout.date_picker_dialog, null);
  
          mDayOfWeekView = (TextView) view.findViewById(R.id.date_picker_header);
          mMonthAndDayView = (LinearLayout) view.findViewById(R.id.date_picker_month_and_day);
          mMonthAndDayView.setOnClickListener(this);
          mSelectedMonthTextView = (TextView) view.findViewById(R.id.date_picker_month);
          mSelectedDayTextView = (TextView) view.findViewById(R.id.date_picker_day);
          mYearView = (TextView) view.findViewById(R.id.date_picker_year);
          mYearView.setOnClickListener(this);
  
          int listPosition = -1;
          int listPositionOffset = 0;
          int currentView = MONTH_AND_DAY_VIEW;
          if (savedInstanceState != null) {
              mWeekStart = savedInstanceState.getInt(KEY_WEEK_START);
              mMinYear = savedInstanceState.getInt(KEY_YEAR_START);
              mMaxYear = savedInstanceState.getInt(KEY_YEAR_END);
              currentView = savedInstanceState.getInt(KEY_CURRENT_VIEW);
              listPosition = savedInstanceState.getInt(KEY_LIST_POSITION);
              listPositionOffset = savedInstanceState.getInt(KEY_LIST_POSITION_OFFSET);
          }
  
          final Activity activity = getActivity();
          mDayPickerView = new SimpleDayPickerView(activity, this);
          mYearPickerView = new YearPickerView(activity, this);
  
          Resources res = getResources();
          mDayPickerDescription = res.getString(R.string.day_picker_description);
          mSelectDay = res.getString(R.string.select_day);
          mYearPickerDescription = res.getString(R.string.year_picker_description);
          mSelectYear = res.getString(R.string.select_year);
  
          mAnimator = (AccessibleDateAnimator) view.findViewById(R.id.animator);
          mAnimator.addView(mDayPickerView);
          mAnimator.addView(mYearPickerView);
          mAnimator.setDateMillis(mCalendar.getTimeInMillis());
          // TODO: Replace with animation decided upon by the design team.
          Animation animation = new AlphaAnimation(0.0f, 1.0f);
          animation.setDuration(ANIMATION_DURATION);
          mAnimator.setInAnimation(animation);
          // TODO: Replace with animation decided upon by the design team.
          Animation animation2 = new AlphaAnimation(1.0f, 0.0f);
          animation2.setDuration(ANIMATION_DURATION);
          mAnimator.setOutAnimation(animation2);
  
          mDoneButton = (Button) view.findViewById(R.id.done);
          mDoneButton.setOnClickListener(new OnClickListener() {
  
              @Override
              public void onClick(View v) {
                  tryVibrate();
                  if (mCallBack != null) {
                      mCallBack.onDateSet(DatePickerDialog.this, mCalendar.get(Calendar.YEAR),
                              mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
                  }
                  dismiss();
              }
          });
  
          updateDisplay(false);
          setCurrentView(currentView);
  
          if (listPosition != -1) {
              if (currentView == MONTH_AND_DAY_VIEW) {
                  mDayPickerView.postSetSelection(listPosition);
              } else if (currentView == YEAR_VIEW) {
                  mYearPickerView.postSetSelectionFromTop(listPosition, listPositionOffset);
              }
          }
  
          mHapticFeedbackController = new HapticFeedbackController(activity);
          return view;
      }
  
      @Override
      public void onResume() {
          super.onResume();
          mHapticFeedbackController.start();
      }
  
      @Override
      public void onPause() {
          super.onPause();
          mHapticFeedbackController.stop();
      }
  
      private void setCurrentView(final int viewIndex) {
          long millis = mCalendar.getTimeInMillis();
  
          switch (viewIndex) {
              case MONTH_AND_DAY_VIEW:
                  ObjectAnimator pulseAnimator = Utils.getPulseAnimator(mMonthAndDayView, 0.9f,
                          1.05f);
                  if (mDelayAnimation) {
                      pulseAnimator.setStartDelay(ANIMATION_DELAY);
                      mDelayAnimation = false;
                  }
                  mDayPickerView.onDateChanged();
                  if (mCurrentView != viewIndex) {
                      mMonthAndDayView.setSelected(true);
                      mYearView.setSelected(false);
                      mAnimator.setDisplayedChild(MONTH_AND_DAY_VIEW);
                      mCurrentView = viewIndex;
                  }
                  pulseAnimator.start();
  
                  int flags = DateUtils.FORMAT_SHOW_DATE;
                  String dayString = DateUtils.formatDateTime(getActivity(), millis, flags);
                  mAnimator.setContentDescription(mDayPickerDescription+": "+dayString);
                  Utils.tryAccessibilityAnnounce(mAnimator, mSelectDay);
                  break;
              case YEAR_VIEW:
                  pulseAnimator = Utils.getPulseAnimator(mYearView, 0.85f, 1.1f);
                  if (mDelayAnimation) {
                      pulseAnimator.setStartDelay(ANIMATION_DELAY);
                      mDelayAnimation = false;
                  }
                  mYearPickerView.onDateChanged();
                  if (mCurrentView != viewIndex) {
                      mMonthAndDayView.setSelected(false);
                      mYearView.setSelected(true);
                      mAnimator.setDisplayedChild(YEAR_VIEW);
                      mCurrentView = viewIndex;
                  }
                  pulseAnimator.start();
  
                  CharSequence yearString = YEAR_FORMAT.format(millis);
                  mAnimator.setContentDescription(mYearPickerDescription+": "+yearString);
                  Utils.tryAccessibilityAnnounce(mAnimator, mSelectYear);
                  break;
          }
      }
  
      private void updateDisplay(boolean announce) {
          if (mDayOfWeekView != null) {
              mDayOfWeekView.setText(mCalendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG,
                      Locale.getDefault()).toUpperCase(Locale.getDefault()));
          }
  
          mSelectedMonthTextView.setText(mCalendar.getDisplayName(Calendar.MONTH, Calendar.SHORT,
                  Locale.getDefault()).toUpperCase(Locale.getDefault()));
          mSelectedDayTextView.setText(DAY_FORMAT.format(mCalendar.getTime()));
          mYearView.setText(YEAR_FORMAT.format(mCalendar.getTime()));
  
          // Accessibility.
          long millis = mCalendar.getTimeInMillis();
          mAnimator.setDateMillis(millis);
          int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
          String monthAndDayText = DateUtils.formatDateTime(getActivity(), millis, flags);
          mMonthAndDayView.setContentDescription(monthAndDayText);
  
          if (announce) {
              flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
              String fullDateText = DateUtils.formatDateTime(getActivity(), millis, flags);
              Utils.tryAccessibilityAnnounce(mAnimator, fullDateText);
          }
      }
  
      public void setFirstDayOfWeek(int startOfWeek) {
          if (startOfWeek < Calendar.SUNDAY || startOfWeek > Calendar.SATURDAY) {
              throw new IllegalArgumentException("Value must be between Calendar.SUNDAY and " +
                      "Calendar.SATURDAY");
          }
          mWeekStart = startOfWeek;
          if (mDayPickerView != null) {
              mDayPickerView.onChange();
          }
      }
  
      public void setYearRange(int startYear, int endYear) {
          if (endYear <= startYear) {
              throw new IllegalArgumentException("Year end must be larger than year start");
          }
          mMinYear = startYear;
          mMaxYear = endYear;
          if (mDayPickerView != null) {
              mDayPickerView.onChange();
          }
      }
  
      /**
       * Sets the minimal date supported by this DatePicker. Dates before (but not including) the
       * specified date will be disallowed from being selected.
       * @param calendar a Calendar object set to the year, month, day desired as the mindate.
       */
      public void setMinDate(Calendar calendar) {
          mMinDate = calendar;
  
          if (mDayPickerView != null) {
              mDayPickerView.onChange();
          }
      }
  
      /**
       * @return The minimal date supported by this DatePicker. Null if it has not been set.
       */
      @Override
      public Calendar getMinDate() {
          return mMinDate;
      }
  
      /**
       * Sets the minimal date supported by this DatePicker. Dates after (but not including) the
       * specified date will be disallowed from being selected.
       * @param calendar a Calendar object set to the year, month, day desired as the maxdate.
       */
      public void setMaxDate(Calendar calendar) {
          mMaxDate = calendar;
  
          if (mDayPickerView != null) {
              mDayPickerView.onChange();
          }
      }
  
      /**
       * @return The maximal date supported by this DatePicker. Null if it has not been set.
       */
      @Override
      public Calendar getMaxDate() {
          return mMaxDate;
      }
  
      public void setOnDateSetListener(OnDateSetListener listener) {
          mCallBack = listener;
      }
  
      // If the newly selected month / year does not contain the currently selected day number,
      // change the selected day number to the last day of the selected month or year.
      //      e.g. Switching from Mar to Apr when Mar 31 is selected -> Apr 30
      //      e.g. Switching from 2012 to 2013 when Feb 29, 2012 is selected -> Feb 28, 2013
      private void adjustDayInMonthIfNeeded(int month, int year) {
          int day = mCalendar.get(Calendar.DAY_OF_MONTH);
          int daysInMonth = Utils.getDaysInMonth(month, year);
          if (day > daysInMonth) {
              mCalendar.set(Calendar.DAY_OF_MONTH, daysInMonth);
          }
      }
  
      @Override
      public void onClick(View v) {
          tryVibrate();
          if (v.getId() == R.id.date_picker_year) {
              setCurrentView(YEAR_VIEW);
          } else if (v.getId() == R.id.date_picker_month_and_day) {
              setCurrentView(MONTH_AND_DAY_VIEW);
          }
      }
  
      @Override
      public void onYearSelected(int year) {
          adjustDayInMonthIfNeeded(mCalendar.get(Calendar.MONTH), year);
          mCalendar.set(Calendar.YEAR, year);
          updatePickers();
          setCurrentView(MONTH_AND_DAY_VIEW);
          updateDisplay(true);
      }
  
      @Override
      public void onDayOfMonthSelected(int year, int month, int day) {
          mCalendar.set(Calendar.YEAR, year);
          mCalendar.set(Calendar.MONTH, month);
          mCalendar.set(Calendar.DAY_OF_MONTH, day);
          updatePickers();
          updateDisplay(true);
      }
  
      private void updatePickers() {
          Iterator<OnDateChangedListener> iterator = mListeners.iterator();
          while (iterator.hasNext()) {
              iterator.next().onDateChanged();
          }
      }
  
  
      @Override
      public CalendarDay getSelectedDay() {
          return new CalendarDay(mCalendar);
      }
  
      @Override
      public int getMinYear() {
          return mMinYear;
      }
  
      @Override
      public int getMaxYear() {
          return mMaxYear;
      }
  
      @Override
      public int getFirstDayOfWeek() {
          return mWeekStart;
      }
  
      @Override
      public void registerOnDateChangedListener(OnDateChangedListener listener) {
          mListeners.add(listener);
      }
  
      @Override
      public void unregisterOnDateChangedListener(OnDateChangedListener listener) {
          mListeners.remove(listener);
      }
  
      @Override
      public void tryVibrate() {
          mHapticFeedbackController.tryVibrate();
      }
  }
  