package com.fsck.k9.activity.compose;
import java.util.Arrays;
import java.util.List;
import android.app.LoaderManager;
import android.app.PendingIntent;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.Toast;
import android.widget.ViewAnimator;
import com.fsck.k9.FontSizes;
import com.fsck.k9.R;
import com.fsck.k9.activity.MessageCompose;
import com.fsck.k9.activity.compose.RecipientPresenter.CryptoMode;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.view.RecipientSelectView;
import com.fsck.k9.view.RecipientSelectView.Recipient;
import com.fsck.k9.view.RecipientSelectView.TokenListener;
public class RecipientMvpView implements OnFocusChangeListener, OnClickListener {
private static final int VIEW_INDEX_HIDDEN = -1;
private static final int VIEW_INDEX_CRYPTO_STATUS_DISABLED = 0;
private static final int VIEW_INDEX_CRYPTO_STATUS_ERROR = 1;
private static final int VIEW_INDEX_CRYPTO_STATUS_NO_RECIPIENTS = 2;
private static final int VIEW_INDEX_CRYPTO_STATUS_ERROR_NO_KEY = 3;
private static final int VIEW_INDEX_CRYPTO_STATUS_DISABLED_NO_KEY = 4;
private static final int VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED = 5;
private static final int VIEW_INDEX_CRYPTO_STATUS_TRUSTED = 6;
private static final int VIEW_INDEX_CRYPTO_STATUS_SIGN_ONLY = 0;
private static final int VIEW_INDEX_CRYPTO_SPECIAL_PGP_INLINE = 0;
private static final int VIEW_INDEX_CRYPTO_SPECIAL_SIGN_ONLY = 1;
private static final int VIEW_INDEX_CRYPTO_SPECIAL_SIGN_ONLY_PGP_INLINE = 2;
private static final int VIEW_INDEX_BCC_EXPANDER_VISIBLE = 0;
private static final int VIEW_INDEX_BCC_EXPANDER_HIDDEN = 1;
private final MessageCompose activity;
private final View ccWrapper;
private final View ccDivider;
private final View bccWrapper;
private final View bccDivider;
private final RecipientSelectView toView;
private final RecipientSelectView ccView;
private final RecipientSelectView bccView;
private final ViewAnimator cryptoStatusView;
private final ViewAnimator recipientExpanderContainer;
private final ViewAnimator cryptoSpecialModeIndicator;
private RecipientPresenter presenter;
public RecipientMvpView(MessageCompose activity) {
this.activity = activity;
toView = (RecipientSelectView) activity.findViewById(R.id.to);
ccView = (RecipientSelectView) activity.findViewById(R.id.cc);
bccView = (RecipientSelectView) activity.findViewById(R.id.bcc);
ccWrapper = activity.findViewById(R.id.cc_wrapper);
ccDivider = activity.findViewById(R.id.cc_divider);
bccWrapper = activity.findViewById(R.id.bcc_wrapper);
bccDivider = activity.findViewById(R.id.bcc_divider);
recipientExpanderContainer = (ViewAnimator) activity.findViewById(R.id.recipient_expander_container);
cryptoStatusView = (ViewAnimator) activity.findViewById(R.id.crypto_status);
cryptoStatusView.setOnClickListener(this);
cryptoSpecialModeIndicator = (ViewAnimator) activity.findViewById(R.id.crypto_special_mode);
cryptoSpecialModeIndicator.setOnClickListener(this);
toView.setOnFocusChangeListener(this);
ccView.setOnFocusChangeListener(this);
bccView.setOnFocusChangeListener(this);
View recipientExpander = activity.findViewById(R.id.recipient_expander);
recipientExpander.setOnClickListener(this);
View toLabel = activity.findViewById(R.id.to_label);
View ccLabel = activity.findViewById(R.id.cc_label);
View bccLabel = activity.findViewById(R.id.bcc_label);
toLabel.setOnClickListener(this);
ccLabel.setOnClickListener(this);
bccLabel.setOnClickListener(this);
}
public void setPresenter(final RecipientPresenter presenter) {
this.presenter = presenter;
if (presenter == null) {
toView.setTokenListener(null);
ccView.setTokenListener(null);
bccView.setTokenListener(null);
return;
}
toView.setTokenListener(new TokenListener<Recipient>() {
@Override
public void onTokenAdded(Recipient recipient) {
presenter.onToTokenAdded();
}
@Override
public void onTokenRemoved(Recipient recipient) {
presenter.onToTokenRemoved();
}
@Override
public void onTokenChanged(Recipient recipient) {
presenter.onToTokenChanged();
}
});
ccView.setTokenListener(new TokenListener<Recipient>() {
@Override
public void onTokenAdded(Recipient recipient) {
presenter.onCcTokenAdded();
}
@Override
public void onTokenRemoved(Recipient recipient) {
presenter.onCcTokenRemoved();
}
@Override
public void onTokenChanged(Recipient recipient) {
presenter.onCcTokenChanged();
}
});
bccView.setTokenListener(new TokenListener<Recipient>() {
@Override
public void onTokenAdded(Recipient recipient) {
presenter.onBccTokenAdded();
}
@Override
public void onTokenRemoved(Recipient recipient) {
presenter.onBccTokenRemoved();
}
@Override
public void onTokenChanged(Recipient recipient) {
presenter.onBccTokenChanged();
}
});
}
public void addTextChangedListener(TextWatcher textWatcher) {
toView.addTextChangedListener(textWatcher);
ccView.addTextChangedListener(textWatcher);
bccView.addTextChangedListener(textWatcher);
}
public void setCryptoProvider(String openPgpProvider) {
toView.setCryptoProvider(openPgpProvider);
ccView.setCryptoProvider(openPgpProvider);
bccView.setCryptoProvider(openPgpProvider);
}
public void requestFocusOnToField() {
toView.requestFocus();
}
public void requestFocusOnCcField() {
ccView.requestFocus();
}
public void requestFocusOnBccField() {
bccView.requestFocus();
}
public void setFontSizes(FontSizes fontSizes, int fontSize) {
fontSizes.setViewTextSize(toView, fontSize);
fontSizes.setViewTextSize(ccView, fontSize);
fontSizes.setViewTextSize(bccView, fontSize);
}
public void addRecipients(RecipientType recipientType, Recipient... recipients) {
switch (recipientType) {
case TO: {
toView.addRecipients(recipients);
break;
}
case CC: {
ccView.addRecipients(recipients);
break;
}
case BCC: {
bccView.addRecipients(recipients);
break;
}
}
}
public void setCcVisibility(boolean visible) {
ccWrapper.setVisibility(visible ? View.VISIBLE : View.GONE);
ccDivider.setVisibility(visible ? View.VISIBLE : View.GONE);
}
public void setBccVisibility(boolean visible) {
bccWrapper.setVisibility(visible ? View.VISIBLE : View.GONE);
bccDivider.setVisibility(visible ? View.VISIBLE : View.GONE);
}
public void setRecipientExpanderVisibility(boolean visible) {
int childToDisplay = visible ? VIEW_INDEX_BCC_EXPANDER_VISIBLE : VIEW_INDEX_BCC_EXPANDER_HIDDEN;
if (recipientExpanderContainer.getDisplayedChild() != childToDisplay) {
recipientExpanderContainer.setDisplayedChild(childToDisplay);
}
}
public boolean isCcVisible() {
return ccWrapper.getVisibility() == View.VISIBLE;
}
public boolean isBccVisible() {
return bccWrapper.getVisibility() == View.VISIBLE;
}
public void showNoRecipientsError() {
toView.setError(toView.getContext().getString(R.string.message_compose_error_no_recipients));
}
public List<Address> getToAddresses() {
return Arrays.asList(toView.getAddresses());
}
public List<Address> getCcAddresses() {
return Arrays.asList(ccView.getAddresses());
}
public List<Address> getBccAddresses() {
return Arrays.asList(bccView.getAddresses());
}
public List<Recipient> getToRecipients() {
return toView.getObjects();
}
public List<Recipient> getCcRecipients() {
return ccView.getObjects();
}
public List<Recipient> getBccRecipients() {
return bccView.getObjects();
}
public boolean recipientToHasUncompletedText() {
return toView.hasUncompletedText();
}
public boolean recipientCcHasUncompletedText() {
return ccView.hasUncompletedText();
}
public boolean recipientBccHasUncompletedText() {
return bccView.hasUncompletedText();
}
public boolean recipientToTryPerformCompletion() {
return toView.tryPerformCompletion();
}
public boolean recipientCcTryPerformCompletion() {
return ccView.tryPerformCompletion();
}
public boolean recipientBccTryPerformCompletion() {
return bccView.tryPerformCompletion();
}
public void showToUncompletedError() {
toView.setError(toView.getContext().getString(R.string.compose_error_incomplete_recipient));
}
public void showCcUncompletedError() {
ccView.setError(ccView.getContext().getString(R.string.compose_error_incomplete_recipient));
}
public void showBccUncompletedError() {
bccView.setError(bccView.getContext().getString(R.string.compose_error_incomplete_recipient));
}
public void showCryptoSpecialMode(CryptoSpecialModeDisplayType cryptoSpecialModeDisplayType) {
boolean shouldBeHidden = cryptoSpecialModeDisplayType.childToDisplay == VIEW_INDEX_HIDDEN;
if (shouldBeHidden) {
cryptoSpecialModeIndicator.setVisibility(View.GONE);
return;
}
cryptoSpecialModeIndicator.setVisibility(View.VISIBLE);
cryptoSpecialModeIndicator.setDisplayedChild(cryptoSpecialModeDisplayType.childToDisplay);
activity.invalidateOptionsMenu();
}
public void showCryptoStatus(CryptoStatusDisplayType cryptoStatusDisplayType) {
boolean shouldBeHidden = cryptoStatusDisplayType.childToDisplay == VIEW_INDEX_HIDDEN;
if (shouldBeHidden) {
cryptoStatusView.setVisibility(View.GONE);
return;
}
cryptoStatusView.setVisibility(View.VISIBLE);
cryptoStatusView.setDisplayedChild(cryptoStatusDisplayType.childToDisplay);
}
public void showContactPicker(int requestCode) {
activity.showContactPicker(requestCode);
}
public void showErrorIsSignOnly() {
Toast.makeText(activity, R.string.error_sign_only_no_encryption, Toast.LENGTH_LONG).show();
}
public void showErrorContactNoAddress() {
Toast.makeText(activity, R.string.error_contact_address_not_found, Toast.LENGTH_LONG).show();
}
public void showErrorOpenPgpConnection() {
Toast.makeText(activity, R.string.error_crypto_provider_connect, Toast.LENGTH_LONG).show();
}
public void showErrorOpenPgpUserInteractionRequired() {
Toast.makeText(activity, R.string.error_crypto_provider_ui_required, Toast.LENGTH_LONG).show();
}
public void showErrorMissingSignKey() {
Toast.makeText(activity, R.string.compose_error_no_signing_key, Toast.LENGTH_LONG).show();
}
public void showErrorPrivateButMissingKeys() {
Toast.makeText(activity, R.string.compose_error_private_missing_keys, Toast.LENGTH_LONG).show();
}
public void showErrorInlineAttach() {
Toast.makeText(activity, R.string.error_crypto_inline_attach, Toast.LENGTH_LONG).show();
}
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (!hasFocus) {
return;
}
switch (view.getId()) {
case R.id.to: {
presenter.onToFocused();
break;
}
case R.id.cc: {
presenter.onCcFocused();
break;
}
case R.id.bcc: {
presenter.onBccFocused();
break;
}
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.to_label: {
presenter.onClickToLabel();
break;
}
case R.id.cc_label: {
presenter.onClickCcLabel();
break;
}
case R.id.bcc_label: {
presenter.onClickBccLabel();
break;
}
case R.id.recipient_expander: {
presenter.onClickRecipientExpander();
break;
}
case R.id.crypto_status: {
presenter.onClickCryptoStatus();
break;
}
case R.id.crypto_special_mode: {
presenter.onClickCryptoSpecialModeIndicator();
}
}
}
public void showCryptoDialog(CryptoMode currentCryptoMode) {
CryptoSettingsDialog dialog = CryptoSettingsDialog.newInstance(currentCryptoMode);
dialog.show(activity.getFragmentManager(), "crypto_settings");
}
public void showOpenPgpInlineDialog(boolean firstTime) {
PgpInlineDialog dialog = PgpInlineDialog.newInstance(firstTime, R.id.crypto_special_mode);
dialog.show(activity.getFragmentManager(), "openpgp_inline");
}
public void showOpenPgpSignOnlyDialog(boolean firstTime) {
PgpSignOnlyDialog dialog = PgpSignOnlyDialog.newInstance(firstTime, R.id.crypto_special_mode);
dialog.show(activity.getFragmentManager(), "openpgp_signonly");
}
public void launchUserInteractionPendingIntent(PendingIntent pendingIntent, int requestCode) {
activity.launchUserInteractionPendingIntent(pendingIntent, requestCode);
}
public void setLoaderManager(LoaderManager loaderManager) {
toView.setLoaderManager(loaderManager);
ccView.setLoaderManager(loaderManager);
bccView.setLoaderManager(loaderManager);
}
public enum CryptoStatusDisplayType {
UNCONFIGURED(VIEW_INDEX_HIDDEN),
UNINITIALIZED(VIEW_INDEX_HIDDEN),
DISABLED(VIEW_INDEX_CRYPTO_STATUS_DISABLED),
SIGN_ONLY(VIEW_INDEX_CRYPTO_STATUS_SIGN_ONLY),
OPPORTUNISTIC_EMPTY(VIEW_INDEX_CRYPTO_STATUS_NO_RECIPIENTS),
OPPORTUNISTIC_NOKEY(VIEW_INDEX_CRYPTO_STATUS_DISABLED_NO_KEY),
OPPORTUNISTIC_UNTRUSTED(VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED),
OPPORTUNISTIC_TRUSTED(VIEW_INDEX_CRYPTO_STATUS_TRUSTED),
PRIVATE_EMPTY(VIEW_INDEX_CRYPTO_STATUS_NO_RECIPIENTS),
PRIVATE_NOKEY(VIEW_INDEX_CRYPTO_STATUS_ERROR_NO_KEY),
PRIVATE_UNTRUSTED(VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED),
PRIVATE_TRUSTED(VIEW_INDEX_CRYPTO_STATUS_TRUSTED),
ERROR(VIEW_INDEX_CRYPTO_STATUS_ERROR);
final int childToDisplay;
CryptoStatusDisplayType(int childToDisplay) {
this.childToDisplay = childToDisplay;
}
}
public enum CryptoSpecialModeDisplayType {
NONE(VIEW_INDEX_HIDDEN),
PGP_INLINE(VIEW_INDEX_CRYPTO_SPECIAL_PGP_INLINE),
SIGN_ONLY(VIEW_INDEX_CRYPTO_SPECIAL_SIGN_ONLY),
SIGN_ONLY_PGP_INLINE(VIEW_INDEX_CRYPTO_SPECIAL_SIGN_ONLY_PGP_INLINE);
final int childToDisplay;
CryptoSpecialModeDisplayType(int childToDisplay) {
this.childToDisplay = childToDisplay;
}
}
}