1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.email.activity.setup;
18
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.app.DialogFragment;
22import android.app.Fragment;
23import android.content.Context;
24import android.content.DialogInterface;
25import android.content.Intent;
26import android.os.Bundle;
27
28import com.android.email.R;
29import com.android.email.setup.AuthenticatorSetupIntentHelper;
30import com.android.emailcommon.provider.Account;
31import com.android.mail.utils.LogUtils;
32
33public class AccountServerSettingsActivity extends AccountSetupActivity implements
34        SecurityRequiredDialogFragment.Callback, CheckSettingsErrorDialogFragment.Callback,
35        AccountCheckSettingsFragment.Callback, AccountServerBaseFragment.Callback,
36        CheckSettingsProgressDialogFragment.Callback {
37
38    /**
39     * {@link com.android.emailcommon.provider.Account}
40     */
41    private static final String EXTRA_ACCOUNT = "account";
42    /**
43     * Incoming or Outgoing settings?
44     */
45    private static final String EXTRA_WHICH_SETTINGS = "whichSettings";
46    private static final String INCOMING_SETTINGS = "incoming";
47    private static final String OUTGOING_SETTINGS = "outgoing";
48
49    private AccountServerBaseFragment mAccountServerFragment;
50
51    public static Intent getIntentForIncoming(final Context context, final Account account) {
52        final Intent intent = new Intent(context, AccountServerSettingsActivity.class);
53        intent.putExtra(EXTRA_ACCOUNT, account);
54        intent.putExtra(EXTRA_WHICH_SETTINGS, INCOMING_SETTINGS);
55        return intent;
56    }
57
58    public static Intent getIntentForOutgoing(final Context context, final Account account) {
59        final Intent intent = new Intent(context, AccountServerSettingsActivity.class);
60        intent.putExtra(EXTRA_ACCOUNT, account);
61        intent.putExtra(EXTRA_WHICH_SETTINGS, OUTGOING_SETTINGS);
62        return intent;
63    }
64
65    @Override
66    public void onCreate(Bundle savedInstanceState) {
67        super.onCreate(savedInstanceState);
68
69        mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_EDIT);
70
71        setContentView(R.layout.account_server_settings);
72        setFinishOnTouchOutside(false);
73
74        if (savedInstanceState == null) {
75            final Account account = getIntent().getParcelableExtra(EXTRA_ACCOUNT);
76            if (account == null) {
77                throw new IllegalArgumentException("No account present in intent");
78            }
79            mSetupData.setAccount(account);
80            final String whichSettings = getIntent().getStringExtra(EXTRA_WHICH_SETTINGS);
81            final AccountServerBaseFragment f;
82            if (OUTGOING_SETTINGS.equals(whichSettings)) {
83                f = AccountSetupOutgoingFragment.newInstance(true);
84            } else {
85                f = AccountSetupIncomingFragment.newInstance(true);
86            }
87            getFragmentManager().beginTransaction()
88                    .add(R.id.account_server_settings_container, f)
89                    .commit();
90        }
91    }
92
93    @Override
94    public void onAttachFragment(Fragment fragment) {
95        super.onAttachFragment(fragment);
96        if (fragment instanceof AccountServerBaseFragment) {
97            mAccountServerFragment = (AccountServerBaseFragment) fragment;
98        }
99    }
100
101    public AccountServerBaseFragment getAccountServerFragment() {
102        return mAccountServerFragment;
103    }
104
105    private void forceBack() {
106        super.onBackPressed();
107    }
108
109    /**
110     * Any time we exit via this pathway we put up the exit-save-changes dialog.
111     */
112    @Override
113    public void onBackPressed() {
114        final AccountServerBaseFragment accountServerFragment = getAccountServerFragment();
115        if (accountServerFragment != null) {
116            if (accountServerFragment.haveSettingsChanged()) {
117                UnsavedChangesDialogFragment dialogFragment =
118                        UnsavedChangesDialogFragment.newInstanceForBack();
119                dialogFragment.show(getFragmentManager(), UnsavedChangesDialogFragment.TAG);
120                return; // Prevent "back" from being handled
121            }
122        }
123        super.onBackPressed();
124    }
125
126    @Override
127    public void onNextButton() {}
128
129    /**
130     * Save process is done, dismiss the fragment.
131     */
132    @Override
133    public void onAccountServerSaveComplete() {
134        super.onBackPressed();
135    }
136
137    @Override
138    public void onAccountServerUIComplete(int checkMode) {
139        final Fragment checkerDialog = CheckSettingsProgressDialogFragment.newInstance(checkMode);
140        final Fragment checkerFragment = AccountCheckSettingsFragment.newInstance(checkMode);
141        getFragmentManager().beginTransaction()
142                .add(checkerDialog, CheckSettingsProgressDialogFragment.TAG)
143                .add(checkerFragment, AccountCheckSettingsFragment.TAG)
144                .commit();
145    }
146
147    @Override
148    public void onCheckSettingsProgressDialogCancel() {
149        dismissCheckSettingsFragment();
150    }
151
152    /**
153     * After verifying a new server configuration as OK, we return here and continue. This kicks
154     * off the save process.
155     */
156    @Override
157    public void onCheckSettingsComplete() {
158        dismissCheckSettingsFragment();
159        final AccountServerBaseFragment f = getAccountServerFragment();
160        if (f != null) {
161            f.saveSettings();
162        }
163    }
164
165    @Override
166    public void onCheckSettingsSecurityRequired(String hostName) {
167        dismissCheckSettingsFragment();
168        SecurityRequiredDialogFragment.newInstance(hostName)
169                .show(getFragmentManager(), SecurityRequiredDialogFragment.TAG);
170    }
171
172    @Override
173    public void onCheckSettingsError(int reason, String message) {
174        dismissCheckSettingsFragment();
175        CheckSettingsErrorDialogFragment.newInstance(reason, message)
176                .show(getFragmentManager(), CheckSettingsErrorDialogFragment.TAG);
177    }
178
179    @Override
180    public void onCheckSettingsAutoDiscoverComplete(int result) {
181        throw new IllegalStateException();
182    }
183
184    private void dismissCheckSettingsFragment() {
185        final Fragment f =
186                getFragmentManager().findFragmentByTag(AccountCheckSettingsFragment.TAG);
187        final Fragment d =
188                getFragmentManager().findFragmentByTag(CheckSettingsProgressDialogFragment.TAG);
189        getFragmentManager().beginTransaction()
190                .remove(f)
191                .remove(d)
192                .commit();
193    }
194
195    @Override
196    public void onSecurityRequiredDialogResult(boolean ok) {
197        if (ok) {
198            final AccountServerBaseFragment f = getAccountServerFragment();
199            if (f != null) {
200                f.saveSettings();
201            }
202        }
203        // else just stay here
204    }
205
206    @Override
207    public void onCheckSettingsErrorDialogEditSettings() {
208        // Just stay here
209    }
210
211    @Override
212    public void onCheckSettingsErrorDialogEditCertificate() {
213        final AccountServerBaseFragment f = getAccountServerFragment();
214        if (f instanceof AccountSetupIncomingFragment) {
215            AccountSetupIncomingFragment asif = (AccountSetupIncomingFragment) f;
216            asif.onCertificateRequested();
217        } else {
218            LogUtils.wtf(LogUtils.TAG, "Tried to change cert on non-incoming screen?");
219        }
220    }
221
222    /**
223     * Dialog fragment to show "exit with unsaved changes?" dialog
224     */
225    public static class UnsavedChangesDialogFragment extends DialogFragment {
226        final static String TAG = "UnsavedChangesDialogFragment";
227
228        /**
229         * Creates a save changes dialog when the user navigates "back".
230         * {@link #onBackPressed()} defines in which case this may be triggered.
231         */
232        public static UnsavedChangesDialogFragment newInstanceForBack() {
233            return new UnsavedChangesDialogFragment();
234        }
235
236        // Force usage of newInstance()
237        public UnsavedChangesDialogFragment() {}
238
239        @Override
240        public Dialog onCreateDialog(Bundle savedInstanceState) {
241            final AccountServerSettingsActivity activity =
242                    (AccountServerSettingsActivity) getActivity();
243
244            return new AlertDialog.Builder(activity)
245                    .setIconAttribute(android.R.attr.alertDialogIcon)
246                    .setTitle(android.R.string.dialog_alert_title)
247                    .setMessage(R.string.account_settings_exit_server_settings)
248                    .setPositiveButton(
249                            android.R.string.ok,
250                            new DialogInterface.OnClickListener() {
251                                @Override
252                                public void onClick(DialogInterface dialog, int which) {
253                                    activity.forceBack();
254                                    dismiss();
255                                }
256                            })
257                    .setNegativeButton(
258                            activity.getString(android.R.string.cancel), null)
259                    .create();
260        }
261    }
262}
263