/*
 *   Copyright 2012 Hai Bison
 *
 *   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 group.pals.android.lib.ui.lockpattern.util;

import group.pals.android.lib.ui.lockpattern.R;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;

/**
 * An implementation of {@link AsyncTask}, used to show {@link ProgressDialog}
 * while doing some background tasks.
 * 
 * @author Hai Bison
 */
public abstract class LoadingDialog<Params, Progress, Result> extends
        AsyncTask<Params, Progress, Result> {

    private static final String CLASSNAME = LoadingDialog.class.getName();

    private final ProgressDialog mDialog;
    /**
     * Default is {@code 500}ms
     */
    private int mDelayTime = 500;
    /**
     * Flag to use along with {@link #mDelayTime}
     */
    private boolean mFinished = false;

    private Throwable mLastException;

    /**
     * Creates new instance.
     * 
     * @param context
     *            the context.
     * @param cancelable
     *            whether the user can cancel the dialog by tapping outside of
     *            it, or by pressing Back button.
     */
    public LoadingDialog(Context context, boolean cancelable) {
        this(context, context.getString(R.string.alp_loading), cancelable);
    }// LoadingDialog()

    /**
     * Creates new instance.
     * 
     * @param context
     *            the context.
     * @param msg
     *            the message.
     * @param cancelable
     *            whether the user can cancel the dialog by tapping outside of
     *            it, or by pressing Back button.
     */
    public LoadingDialog(Context context, CharSequence msg, boolean cancelable) {
        mDialog = new ProgressDialog(context);
        mDialog.setMessage(msg);
        mDialog.setIndeterminate(true);
        mDialog.setCancelable(cancelable);

        if (cancelable) {
            mDialog.setCanceledOnTouchOutside(true);
            mDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {

                @Override
                public void onCancel(DialogInterface dialog) {
                    cancel(true);
                }// onCancel()

            });
        }
    }// LoadingDialog()

    /**
     * If you override this method, you must call {@code super.onPreExecute()}
     * at beginning of the method.
     */
    @Override
    protected void onPreExecute() {
        new Handler().postDelayed(new Runnable() {

            @Override
            public void run() {
                if (!mFinished) {
                    try {
                        /*
                         * Sometime the activity has been finished before we
                         * show this dialog, it will raise error.
                         */
                        mDialog.show();
                    } catch (Throwable t) {
                        // TODO
                        Log.e(CLASSNAME, "onPreExecute() - show dialog: " + t);
                    }
                }
            }
        }, getDelayTime());
    }// onPreExecute()

    /**
     * If you override this method, you must call
     * {@code super.onPostExecute(result)} at beginning of the method.
     */
    @Override
    protected void onPostExecute(Result result) {
        doFinish();
    }// onPostExecute()

    /**
     * If you override this method, you must call {@code super.onCancelled()} at
     * beginning of the method.
     */
    @Override
    protected void onCancelled() {
        doFinish();
        super.onCancelled();
    }// onCancelled()

    private void doFinish() {
        mFinished = true;
        try {
            /*
             * Sometime the activity has been finished before we dismiss this
             * dialog, it will raise error.
             */
            mDialog.dismiss();
        } catch (Throwable t) {
            // TODO
            Log.e(CLASSNAME, "doFinish() - dismiss dialog: " + t);
        }
    }// doFinish()

    /**
     * Gets the delay time before showing the dialog.
     * 
     * @return the delay time
     */
    public int getDelayTime() {
        return mDelayTime;
    }// getDelayTime()

    /**
     * Sets the delay time before showing the dialog.
     * 
     * @param delayTime
     *            the delay time to set
     * @return the instance of this dialog, for chaining multiple calls into a
     *         single statement.
     */
    public LoadingDialog<Params, Progress, Result> setDelayTime(int delayTime) {
        mDelayTime = delayTime >= 0 ? delayTime : 0;
        return this;
    }// setDelayTime()

    /**
     * Sets last exception. This method is useful in case an exception raises
     * inside {@link #doInBackground(Void...)}
     * 
     * @param t
     *            {@link Throwable}
     */
    protected void setLastException(Throwable t) {
        mLastException = t;
    }// setLastException()

    /**
     * Gets last exception.
     * 
     * @return {@link Throwable}
     */
    protected Throwable getLastException() {
        return mLastException;
    }// getLastException()

}

@@ -1860,58 +1860,546 @@
 t, c
-ontext.getString(R.string.alp_loading), cancelable
+ancelable, R.string.alp_loading);%0A    %7D// LoadingDialog()%0A%0A    /**%0A     * Creates new instance.%0A     * %0A     * @param context%0A     *            the context.%0A     * @param cancelable%0A     *            whether the user can cancel the dialog by tapping outside of%0A     *            it, or by pressing Back button.%0A     * @param msgId%0A     *            the resource ID of the message to be displayed.%0A     */%0A    public LoadingDialog(Context context, boolean cancelable, int msgId) %7B%0A        this(context, cancelable, context.getString(msgId)
 );%0A 
@@ -2524,57 +2524,8 @@
 xt.%0A
-     * @param msg%0A     *            the message.%0A
     
@@ -2666,32 +2666,92 @@
 ng Back button.%0A
+     * @param msg%0A     *            the message to display.%0A
      */%0A    publ
@@ -2788,26 +2788,8 @@
 xt, 
-CharSequence msg, 
 bool
@@ -2794,32 +2794,50 @@
 olean cancelable
+, CharSequence msg
 ) %7B%0A        mDia
@@ -2894,19 +2894,29 @@
 .set
-Message(msg
+Cancelable(cancelable
 );%0A 
@@ -2937,26 +2937,19 @@
 .set
-Indeterminate(true
+Message(msg
 );%0A 
@@ -2966,36 +2966,33 @@
 alog.set
-Cancelable(cancelabl
+Indeterminate(tru
 e);%0A%0A   

Optimize code.