content: /*
   * Copyright (C) 2017 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.example.android.autofill.app.commoncases;
  
  import android.content.Intent;
  import android.graphics.drawable.Drawable;
  import android.os.Bundle;
  import android.support.annotation.DrawableRes;
  import android.support.annotation.NonNull;
  import android.support.annotation.Nullable;
  import android.support.annotation.RequiresApi;
  import android.support.annotation.StringRes;
  import android.support.v7.app.AppCompatActivity;
  import android.support.v7.recyclerview.extensions.ListAdapter;
  import android.support.v7.util.DiffUtil;
  import android.support.v7.widget.DividerItemDecoration;
  import android.support.v7.widget.LinearLayoutManager;
  import android.support.v7.widget.RecyclerView;
  import android.text.Editable;
  import android.text.InputType;
  import android.text.TextWatcher;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.autofill.AutofillId;
  import android.view.autofill.AutofillManager;
  import android.widget.EditText;
  import android.widget.ImageView;
  import android.widget.TextView;
  
  import com.example.android.autofill.app.R;
  import com.example.android.autofill.app.WelcomeActivity;
  
  import java.util.Arrays;
  import java.util.List;
  
  /**
   * This is mostly a normal Activity containing a RecyclerView. The only difference is, the rows in
   * the RecyclerView have autofillable fields. Therefore, when we bind data to a recycled view, we
   * need to also set the {@link AutofillId} on the view.
   */
  @RequiresApi(28)
  public class RecyclerViewActivity extends AppCompatActivity {
      private AutofillManager mAfm;
      private List<FieldMetadata> mFields;
      private FieldAdapter mFieldAdapter;
  
      @Override
      protected void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.recycler_view_activity);
          RecyclerView recyclerView = findViewById(R.id.recyclerView);
          mAfm = getSystemService(AutofillManager.class);
  
          // Init RecyclerView
          LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
          DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(
                  recyclerView.getContext(), layoutManager.getOrientation());
          recyclerView.addItemDecoration(dividerItemDecoration);
          mFields = initList();
          mFieldAdapter = new FieldAdapter(mFields);
          recyclerView.setAdapter(mFieldAdapter);
          recyclerView.setLayoutManager(layoutManager);
  
          // Init submit and clear buttons.
          findViewById(R.id.submitButton).setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  submit();
              }
          });
          findViewById(R.id.clearButton).setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  AutofillManager afm = getSystemService(AutofillManager.class);
                  if (afm != null) {
                      afm.cancel();
                  }
                  resetFields();
              }
          });
      }
  
      private void resetFields() {
          for (FieldMetadata fieldMetadata : mFields) {
              fieldMetadata.setEnteredText("");
          }
          mFieldAdapter.notifyDataSetChanged();
      }
  
      private void submit() {
          Intent intent = WelcomeActivity.getStartActivityIntent(RecyclerViewActivity.this);
          startActivity(intent);
          finish();
      }
  
      public List<FieldMetadata> initList() {
          return Arrays.asList(
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_NAME,
                          R.string.recycler_view_label_name,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_TEXT
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "bday-month",
                          R.string.recycler_view_label_birthday_month,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_EMAIL_ADDRESS,
                          R.string.recycler_view_label_email,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_PHONE,
                          R.string.recycler_view_label_phone,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_PHONE
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "tel_extension",
                          R.string.recycler_view_label_tel_extension,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_PHONE
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_CREDIT_CARD_NUMBER,
                          R.string.recycler_view_label_cc_number,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE,
                          R.string.recycler_view_label_cc_sc,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH,
                          R.string.recycler_view_label_cc_exp_month,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
                          R.string.recycler_view_label_cc_exp_year,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "address-line1",
                          R.string.recycler_view_label_address_line_1,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "address-line2",
                          R.string.recycler_view_label_address_line_2,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "address-line3",
                          R.string.recycler_view_label_address_line_3,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          View.AUTOFILL_HINT_POSTAL_CODE,
                          R.string.recycler_view_label_postal_code,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  ),
                  new FieldMetadata(
                          mAfm.getNextAutofillId(),
                          "bday-year",
                          R.string.recycler_view_label_birthday_year,
                          R.drawable.ic_person_black_24dp,
                          InputType.TYPE_CLASS_NUMBER
                  )
          );
      }
  
      static class FieldAdapter extends ListAdapter<FieldMetadata, FieldViewHolder> {
          private List<FieldMetadata> mFields;
          public FieldAdapter(List<FieldMetadata> fields) {
              super(new FieldDiff());
              mFields = fields;
              submitList(mFields);
          }
  
          @NonNull
          @Override
          public FieldViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
              return new FieldViewHolder(LayoutInflater.from(parent.getContext())
                      .inflate(R.layout.user_data_field, parent, false),
                      new FieldWatcher(mFields));
          }
  
          @Override
          public void onBindViewHolder(@NonNull FieldViewHolder holder, int position) {
              holder.bind(getItem(position));
          }
      }
  
      static class FieldViewHolder extends RecyclerView.ViewHolder {
          ImageView mIcon;
          TextView mLabel;
          EditText mField;
          FieldWatcher mWatcher;
  
          public FieldViewHolder(@NonNull View itemView, FieldWatcher textWatcher) {
              super(itemView);
              mIcon = itemView.findViewById(R.id.icon);
              mLabel = itemView.findViewById(R.id.label);
              mField = itemView.findViewById(R.id.field);
              mWatcher = textWatcher;
              mField.addTextChangedListener(mWatcher);
          }
  
          void bind(FieldMetadata fieldMetadata) {
              mWatcher.updatePosition(getAdapterPosition());
              Drawable drawable = mIcon.getResources().getDrawable(fieldMetadata.getIconRes());
              mIcon.setImageDrawable(drawable);
              mLabel.setText(fieldMetadata.getLabelRes());
              mField.setAutofillHints(fieldMetadata.getAutofillHint());
              mField.setInputType(fieldMetadata.getInputType());
              mField.setText(fieldMetadata.getEnteredText());
  
              // IMPORTANT: setAutofillId of recycled View.
              mField.setAutofillId(fieldMetadata.getAutofillId());
          }
      }
  
      /**
       * TextWatcher implementation to ensure EditTexts get recycled properly.
       */
      static class FieldWatcher implements TextWatcher {
          private int mPosition;
          private List<FieldMetadata> mFields;
  
          public FieldWatcher(List<FieldMetadata> fields) {
              mFields = fields;
          }
  
          public void updatePosition(int position) {
              this.mPosition = position;
          }
  
          @Override
          public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
              // NO-OP
          }
  
          @Override
          public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
              mFields.get(mPosition).setEnteredText(charSequence);
          }
  
          @Override
          public void afterTextChanged(Editable editable) {
              // NO-OP
          }
      }
  
      /**
       * Model class that holds all of the data needed for a row in the {@link RecyclerView}.
       */
      static class FieldMetadata {
          AutofillId mAutofillId;
          String mAutofillHint;
          @StringRes int mLabelRes;
          @DrawableRes int mIconRes;
          int mInputType;
          CharSequence mEnteredText = "";
  
          FieldMetadata(AutofillId autofillId, String autofillHint, @StringRes int labelRes,
                  @DrawableRes int iconRes, int inputType) {
              mAutofillId = autofillId;
              mAutofillHint = autofillHint;
              mLabelRes = labelRes;
              mIconRes = iconRes;
              mInputType = inputType;
          }
  
          public AutofillId getAutofillId() {
              return mAutofillId;
          }
  
          public String getAutofillHint() {
              return mAutofillHint;
          }
  
          public int getLabelRes() {
              return mLabelRes;
          }
  
          public int getIconRes() {
              return mIconRes;
          }
  
          public int getInputType() {
              return mInputType;
          }
  
          public void setEnteredText(CharSequence enteredText) {
              mEnteredText = enteredText;
          }
  
          public CharSequence getEnteredText() {
              return mEnteredText;
          }
      }
  
      static class FieldDiff extends DiffUtil.ItemCallback<FieldMetadata> {
          @Override
          public boolean areItemsTheSame(@NonNull FieldMetadata oldItem,
                  @NonNull FieldMetadata newItem) {
              return oldItem == newItem;
          }
  
          @Override
          public boolean areContentsTheSame(@NonNull FieldMetadata oldItem,
                  @NonNull FieldMetadata newItem) {
              return oldItem.equals(newItem);
          }
      }
  }
  