/**
   * Set the internal state for this view, given a current {@link EntityDelta} state and the {@link
   * ContactsSource} that apply to that state.
   *
   * <p>TODO: make this more generic using data from the source
   */
  @Override
  public void setState(EntityDelta state, ContactsSource source, ViewIdGenerator vig) {
    // Remove any existing sections
    mGeneral.removeAllViews();

    // Bail if invalid state or source
    if (state == null || source == null) return;

    // Make sure we have StructuredName
    EntityModifier.ensureKindExists(state, source, StructuredName.CONTENT_ITEM_TYPE);

    // Fill in the header info
    ValuesDelta values = state.getValues();
    String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
    CharSequence accountType = source.getDisplayLabel(mContext);
    if (TextUtils.isEmpty(accountType)) {
      accountType = mContext.getString(R.string.account_phone);
    }
    if (!TextUtils.isEmpty(accountName)) {
      mHeaderAccountName.setText(mContext.getString(R.string.from_account_format, accountName));
    }
    mHeaderAccountType.setText(mContext.getString(R.string.account_type_format, accountType));
    mHeaderIcon.setImageDrawable(source.getDisplayIcon(mContext));

    mRawContactId = values.getAsLong(RawContacts._ID);

    ValuesDelta primary;

    // Photo
    DataKind kind = source.getKindForMimetype(Photo.CONTENT_ITEM_TYPE);
    if (kind != null) {
      EntityModifier.ensureKindExists(state, source, Photo.CONTENT_ITEM_TYPE);
      mHasPhotoEditor = (source.getKindForMimetype(Photo.CONTENT_ITEM_TYPE) != null);
      primary = state.getPrimaryEntry(Photo.CONTENT_ITEM_TYPE);
      mPhoto.setValues(kind, primary, state, source.readOnly, vig);
      if (!mHasPhotoEditor || !mPhoto.hasSetPhoto()) {
        mPhotoStub.setVisibility(View.GONE);
      } else {
        mPhotoStub.setVisibility(View.VISIBLE);
      }
    } else {
      mPhotoStub.setVisibility(View.VISIBLE);
    }

    // Name
    primary = state.getPrimaryEntry(StructuredName.CONTENT_ITEM_TYPE);
    mName.setText(primary.getAsString(StructuredName.DISPLAY_NAME));

    // Read only warning
    mReadOnlyWarning.setText(mContext.getString(R.string.contact_read_only, accountType));

    // Phones
    ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
    if (phones != null) {
      for (ValuesDelta phone : phones) {
        View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false);
        TextView v;
        v = (TextView) field.findViewById(R.id.label);
        v.setText(mContext.getText(R.string.phoneLabelsGroup));
        v = (TextView) field.findViewById(R.id.data);
        v.setText(PhoneNumberFormatUtilEx.formatNumber(phone.getAsString(Phone.NUMBER)));
        mGeneral.addView(field);
      }
    }

    // Emails
    ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE);
    if (emails != null) {
      for (ValuesDelta email : emails) {
        View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false);
        TextView v;
        v = (TextView) field.findViewById(R.id.label);
        v.setText(mContext.getText(R.string.emailLabelsGroup));
        v = (TextView) field.findViewById(R.id.data);
        v.setText(email.getAsString(Email.DATA));
        mGeneral.addView(field);
      }
    }

    // Hide mGeneral if it's empty
    if (mGeneral.getChildCount() > 0) {
      mGeneral.setVisibility(View.VISIBLE);
    } else {
      mGeneral.setVisibility(View.GONE);
    }
  }