/*
 * Copyright (C) 2009 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.phone;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.SystemProperties;
import android.util.Log;

import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;

/**
 * Displays dialog that enables users to exit Emergency Callback Mode
 *
 * @see EmergencyCallbackModeService
 */
public class EmergencyCallbackModeExitDialog extends Activity implements OnDismissListener {

    private static final String TAG = "EmergencyCallbackMode";

    /** Intent to trigger the Emergency Callback Mode exit dialog */
    static final String ACTION_SHOW_ECM_EXIT_DIALOG =
            "com.android.phone.action.ACTION_SHOW_ECM_EXIT_DIALOG";
    /** Used to get the users choice from the return Intent's extra */
    public static final String EXTRA_EXIT_ECM_RESULT = "exit_ecm_result";

    public static final int EXIT_ECM_BLOCK_OTHERS = 1;
    public static final int EXIT_ECM_DIALOG = 2;
    public static final int EXIT_ECM_PROGRESS_DIALOG = 3;
    public static final int EXIT_ECM_IN_EMERGENCY_CALL_DIALOG = 4;

    AlertDialog mAlertDialog = null;
    ProgressDialog mProgressDialog = null;
    CountDownTimer mTimer = null;
    EmergencyCallbackModeService mService = null;
    Handler mHandler = null;
    int mDialogType = 0;
    long mEcmTimeout = 0;
    private boolean mInEmergencyCall = false;
    private static final int ECM_TIMER_RESET = 1;
    private Phone mPhone = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Check if phone is in Emergency Callback Mode. If not, exit.
        final boolean isInEcm = Boolean.parseBoolean(
                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
        Log.i(TAG, "ECMModeExitDialog launched - isInEcm: " + isInEcm);
        if (!isInEcm) {
            finish();
            return;
        }

        mHandler = new Handler();

        // Start thread that will wait for the connection completion so that it can get
        // timeout value from the service
        Thread waitForConnectionCompleteThread = new Thread(null, mTask,
                "EcmExitDialogWaitThread");
        waitForConnectionCompleteThread.start();

        // Register ECM timer reset notfication
        mPhone = PhoneGlobals.getPhone();
        mPhone.registerForEcmTimerReset(mTimerResetHandler, ECM_TIMER_RESET, null);

        // Register receiver for intent closing the dialog
        IntentFilter filter = new IntentFilter();
        filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
        registerReceiver(mEcmExitReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        try {
            unregisterReceiver(mEcmExitReceiver);
        } catch (IllegalArgumentException e) {
            // Receiver was never registered - silently ignore.
        }
        // Unregister ECM timer reset notification
        if (mPhone != null) {
            mPhone.unregisterForEcmTimerReset(mHandler);
        }
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mDialogType = savedInstanceState.getInt("DIALOG_TYPE");
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("DIALOG_TYPE", mDialogType);
    }

    /**
     * Waits until bind to the service completes
     */
    private Runnable mTask = new Runnable() {
        public void run() {
            Looper.prepare();

            // Bind to the remote service
            bindService(new Intent(EmergencyCallbackModeExitDialog.this,
                    EmergencyCallbackModeService.class), mConnection, Context.BIND_AUTO_CREATE);

            // Wait for bind to finish
            synchronized (EmergencyCallbackModeExitDialog.this) {
                try {
                    if (mService == null) {
                        EmergencyCallbackModeExitDialog.this.wait();
                    }
                } catch (InterruptedException e) {
                    Log.d("ECM", "EmergencyCallbackModeExitDialog InterruptedException: "
                            + e.getMessage());
                    e.printStackTrace();
                }
            }

            // Get timeout value and call state from the service
            if (mService != null) {
                mEcmTimeout = mService.getEmergencyCallbackModeTimeout();
                mInEmergencyCall = mService.getEmergencyCallbackModeCallState();
                try {
                    // Unbind from remote service
                    unbindService(mConnection);
                } catch (IllegalArgumentException e) {
                    // Failed to unbind from service. Don't crash as this brings down the entire
                    // radio.
                    Log.w(TAG, "Failed to unbind from EmergencyCallbackModeService");
                }
            }

            // Show dialog
            mHandler.post(new Runnable() {
                public void run() {
                    showEmergencyCallbackModeExitDialog();
                }
            });
        }
    };

    /**
     * Shows Emergency Callback Mode dialog and starts countdown timer
     */
    private void showEmergencyCallbackModeExitDialog() {
        if (!this.isResumed()) {
            Log.w(TAG, "Tried to show dialog, but activity was already finished");
            return;
        }
        if(mInEmergencyCall) {
            mDialogType = EXIT_ECM_IN_EMERGENCY_CALL_DIALOG;
            showDialog(EXIT_ECM_IN_EMERGENCY_CALL_DIALOG);
        } else {
            if (getIntent().getAction().equals(
                    TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS)) {
                mDialogType = EXIT_ECM_BLOCK_OTHERS;
                showDialog(EXIT_ECM_BLOCK_OTHERS);
            } else if (getIntent().getAction().equals(ACTION_SHOW_ECM_EXIT_DIALOG)) {
                mDialogType = EXIT_ECM_DIALOG;
                showDialog(EXIT_ECM_DIALOG);
            }

            mTimer = new CountDownTimer(mEcmTimeout, 1000) {
                @Override
                public void onTick(long millisUntilFinished) {
                    CharSequence text = getDialogText(millisUntilFinished);
                    mAlertDialog.setMessage(text);
                }

                @Override
                public void onFinish() {
                    //Do nothing
                }
            }.start();
        }
    }

    /**
     * Creates dialog that enables users to exit Emergency Callback Mode
     */
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case EXIT_ECM_BLOCK_OTHERS:
        case EXIT_ECM_DIALOG:
            CharSequence text = getDialogText(mEcmTimeout);
            mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
                    .setIcon(R.drawable.ic_emergency_callback_mode)
                    .setTitle(R.string.phone_in_ecm_notification_title)
                    .setMessage(text)
                    .setPositiveButton(R.string.alert_dialog_yes,
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog,int whichButton) {
                                    // User clicked Yes. Exit Emergency Callback Mode.
                                    mPhone.exitEmergencyCallbackMode();

                                    // Show progress dialog
                                    showDialog(EXIT_ECM_PROGRESS_DIALOG);
                                    mTimer.cancel();
                                }
                            })
                    .setNegativeButton(R.string.alert_dialog_no,
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    // User clicked No
                                    setResult(RESULT_OK, (new Intent()).putExtra(
                                            EXTRA_EXIT_ECM_RESULT, false));
                                    finish();
                                }
                            }).create();
            mAlertDialog.setOnDismissListener(this);
            return mAlertDialog;

        case EXIT_ECM_IN_EMERGENCY_CALL_DIALOG:
            mAlertDialog = new AlertDialog.Builder(EmergencyCallbackModeExitDialog.this)
                    .setIcon(R.drawable.ic_emergency_callback_mode)
                    .setTitle(R.string.phone_in_ecm_notification_title)
                    .setMessage(R.string.alert_dialog_in_ecm_call)
                    .setNeutralButton(R.string.alert_dialog_dismiss,
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    // User clicked Dismiss
                                    setResult(RESULT_OK, (new Intent()).putExtra(
                                            EXTRA_EXIT_ECM_RESULT, false));
                                    finish();
                                }
                            }).create();
            mAlertDialog.setOnDismissListener(this);
            return mAlertDialog;

        case EXIT_ECM_PROGRESS_DIALOG:
            mProgressDialog = new ProgressDialog(EmergencyCallbackModeExitDialog.this);
            mProgressDialog.setMessage(getText(R.string.progress_dialog_exiting_ecm));
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.setCancelable(false);
            return mProgressDialog;

        default:
            return null;
        }
    }

    /**
     * Returns dialog box text with updated timeout value
     */
    private CharSequence getDialogText(long millisUntilFinished) {
        // Format time
        int minutes = (int)(millisUntilFinished / 60000);
        String time = String.format("%d:%02d", minutes,
                (millisUntilFinished % 60000) / 1000);

        switch (mDialogType) {
        case EXIT_ECM_BLOCK_OTHERS:
            return String.format(getResources().getQuantityText(
                    R.plurals.alert_dialog_not_avaialble_in_ecm, minutes).toString(), time);
        case EXIT_ECM_DIALOG:
            return String.format(getResources().getQuantityText(R.plurals.alert_dialog_exit_ecm,
                    minutes).toString(), time);
        }
        return null;
    }

    /**
     * Closes activity when dialog is dismissed
     */
    @Override
    public void onDismiss(DialogInterface dialog) {
        EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
                .putExtra(EXTRA_EXIT_ECM_RESULT, false));
        finish();
    }

    /**
     * Listens for Emergency Callback Mode state change intents
     */
    private BroadcastReceiver mEcmExitReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Received exit Emergency Callback Mode notification close all dialogs
            if (intent.getAction().equals(
                    TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
                if (intent.getBooleanExtra("phoneinECMState", false) == false) {
                    if (mAlertDialog != null)
                        mAlertDialog.dismiss();
                    if (mProgressDialog != null)
                        mProgressDialog.dismiss();
                    EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
                            .putExtra(EXTRA_EXIT_ECM_RESULT, true));
                    finish();
                }
            }
        }
    };

    /**
     * Class for interacting with the interface of the service
     */
    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            mService = ((EmergencyCallbackModeService.LocalBinder)service).getService();
            // Notify thread that connection is ready
            synchronized (EmergencyCallbackModeExitDialog.this) {
                EmergencyCallbackModeExitDialog.this.notify();
            }
        }

        public void onServiceDisconnected(ComponentName className) {
            mService = null;
        }
    };

    /**
     * Class for receiving framework timer reset notifications
     */
    private Handler mTimerResetHandler = new Handler () {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case ECM_TIMER_RESET:
                    if(!((Boolean)((AsyncResult) msg.obj).result).booleanValue()) {
                        EmergencyCallbackModeExitDialog.this.setResult(RESULT_OK, (new Intent())
                                .putExtra(EXTRA_EXIT_ECM_RESULT, false));
                        finish();
                    }
                    break;
            }
        }
    };
}
