/*
 * Copyright (C) 2012 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.mms.ui;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;


/**
 * This AsyncDialog class is used to execute a runnable in a background thread and once that
 * finishes, execute a runnable on the UI thread. If the background runnable task takes longer
 * than half a second, a progress modal dialog is displayed.
 *
 */
public class AsyncDialog {
    private ProgressDialog mProgressDialog;
    private final Activity mActivity;
    private final Handler mHandler;

    public AsyncDialog(Activity activity) {
        mActivity = activity;
        mHandler = new Handler();
    }

    /**
     * Asynchronously executes a task while blocking the UI with a progress spinner.
     *
     * Must be invoked by the UI thread.  No exceptions!
     *
     * @param backgroundTask the work to be done in the background wrapped in a Runnable
     * @param postExecuteTask an optional runnable to run on the UI thread when the background
     * runnable is finished
     * @param dialogStringId the id of the string to be shown in the dialog
     */
    public void runAsync(final Runnable backgroundTask,
            final Runnable postExecuteTask, final int dialogStringId) {
        new ModalDialogAsyncTask(dialogStringId, postExecuteTask)
            .execute(new Runnable[] {backgroundTask});
    }

    // Shows the activity's progress spinner. Should be canceled if exiting the activity.
    private Runnable mShowProgressDialogRunnable = new Runnable() {
        @Override
        public void run() {
            if (mProgressDialog != null) {
                mProgressDialog.show();
            }
        }
    };

    public void clearPendingProgressDialog() {
        // remove any callback to display a progress spinner
        mHandler.removeCallbacks(mShowProgressDialogRunnable);
        // clear the dialog so any pending dialog.dismiss() call can be avoided
        mProgressDialog = null;
    }

    /**
     * Asynchronously performs tasks specified by Runnables.
     * Displays a progress spinner while the tasks are running.  The progress spinner
     * will only show if tasks have not finished after a certain amount of time.
     *
     * This AsyncTask must be instantiated and invoked on the UI thread.
     *
     * TODO: Need to implement a way for the background thread to pass a result to
     * the onPostExecute thread. AsyncTask already provides this functionality.
     */
    private class ModalDialogAsyncTask extends AsyncTask<Runnable, Void, Void> {
        final Runnable mPostExecuteTask;

        /**
         * Creates the Task with the specified string id to be shown in the dialog
         */
        public ModalDialogAsyncTask(int dialogStringId,
                final Runnable postExecuteTask) {
            mPostExecuteTask = postExecuteTask;
            // lazy initialization of progress dialog for loading attachments
            if (mProgressDialog == null) {
                mProgressDialog = createProgressDialog();
            }
            mProgressDialog.setMessage(mActivity.getText(dialogStringId));
        }

        /**
         * Initializes the progress dialog with its intended settings.
         */
        private ProgressDialog createProgressDialog() {
            ProgressDialog dialog = new ProgressDialog(mActivity);
            dialog.setIndeterminate(true);
            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            dialog.setCanceledOnTouchOutside(false);
            dialog.setCancelable(false);
            return dialog;
        }

        /**
         * Activates a progress spinner on the UI.  This assumes the UI has invoked this Task.
         */
        @Override
        protected void onPreExecute() {
            // activate spinner after half a second
            mHandler.postDelayed(mShowProgressDialogRunnable, 500);
        }

        /**
         * Perform the specified Runnable tasks on a background thread
         */
        @Override
        protected Void doInBackground(Runnable... params) {
            if (params != null) {
                try {
                    for (int i = 0; i < params.length; i++) {
                        params[i].run();
                    }

                    // Test code. Uncomment this block to test the progress dialog popping up.
//                    try {
//                        Thread.sleep(2000);
//                    } catch (Exception e) {
//                    }
                } finally {
                    // Cancel pending display of the progress bar if the background task has
                    // finished before the progress bar has popped up.
                    mHandler.removeCallbacks(mShowProgressDialogRunnable);
                }
            }
            return null;
        }

        /**
         * Deactivates the progress spinner on the UI. This assumes the UI has invoked this Task.
         */
        @Override
        protected void onPostExecute(Void result) {
            if (mActivity.isFinishing()) {
                return;
            }
            if (mProgressDialog != null && mProgressDialog.isShowing()) {
                mProgressDialog.dismiss();
            }
            if (mPostExecuteTask != null) {
                mPostExecuteTask.run();
            }
        }
    }
}