/*
 * Copyright (C) 2011 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 com.android.internal.telephony.CallManager;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.phone.Constants.CallStatusCode;
import com.android.phone.InCallUiState.ProgressIndicationType;

import android.content.Context;
import android.content.Intent;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.ServiceState;
import android.util.Log;


/**
 * Helper class for the {@link CallController} that implements special
 * behavior related to emergency calls.  Specifically, this class handles
 * the case of the user trying to dial an emergency number while the radio
 * is off (i.e. the device is in airplane mode), by forcibly turning the
 * radio back on, waiting for it to come up, and then retrying the
 * emergency call.
 *
 * This class is instantiated lazily (the first time the user attempts to
 * make an emergency call from airplane mode) by the the
 * {@link CallController} singleton.
 */
public class EmergencyCallHelper extends Handler {
    private static final String TAG = "EmergencyCallHelper";
    private static final boolean DBG = false;

    // Number of times to retry the call, and time between retry attempts.
    public static final int MAX_NUM_RETRIES = 6;
    public static final long TIME_BETWEEN_RETRIES = 5000;  // msec

    // Timeout used with our wake lock (just as a safety valve to make
    // sure we don't hold it forever).
    public static final long WAKE_LOCK_TIMEOUT = 5 * 60 * 1000;  // 5 minutes in msec

    // Handler message codes; see handleMessage()
    private static final int START_SEQUENCE = 1;
    private static final int SERVICE_STATE_CHANGED = 2;
    private static final int DISCONNECT = 3;
    private static final int RETRY_TIMEOUT = 4;

    private CallController mCallController;
    private PhoneGlobals mApp;
    private CallManager mCM;
    private Phone mPhone;
    private String mNumber;  // The emergency number we're trying to dial
    private int mNumRetriesSoFar;

    // Wake lock we hold while running the whole sequence
    private PowerManager.WakeLock mPartialWakeLock;

    public EmergencyCallHelper(CallController callController) {
        if (DBG) log("EmergencyCallHelper constructor...");
        mCallController = callController;
        mApp = PhoneGlobals.getInstance();
        mCM =  mApp.mCM;
    }

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case START_SEQUENCE:
                startSequenceInternal(msg);
                break;
            case SERVICE_STATE_CHANGED:
                onServiceStateChanged(msg);
                break;
            case DISCONNECT:
                onDisconnect(msg);
                break;
            case RETRY_TIMEOUT:
                onRetryTimeout();
                break;
            default:
                Log.wtf(TAG, "handleMessage: unexpected message: " + msg);
                break;
        }
    }

    /**
     * Starts the "emergency call from airplane mode" sequence.
     *
     * This is the (single) external API of the EmergencyCallHelper class.
     * This method is called from the CallController placeCall() sequence
     * if the user dials a valid emergency number, but the radio is
     * powered-off (presumably due to airplane mode.)
     *
     * This method kicks off the following sequence:
     * - Power on the radio
     * - Listen for the service state change event telling us the radio has come up
     * - Then launch the emergency call
     * - Retry if the call fails with an OUT_OF_SERVICE error
     * - Retry if we've gone 5 seconds without any response from the radio
     * - Finally, clean up any leftover state (progress UI, wake locks, etc.)
     *
     * This method is safe to call from any thread, since it simply posts
     * a message to the EmergencyCallHelper's handler (thus ensuring that
     * the rest of the sequence is entirely serialized, and runs only on
     * the handler thread.)
     *
     * This method does *not* force the in-call UI to come up; our caller
     * is responsible for doing that (presumably by calling
     * PhoneApp.displayCallScreen().)
     */
    public void startEmergencyCallFromAirplaneModeSequence(String number) {
        if (DBG) log("startEmergencyCallFromAirplaneModeSequence('" + number + "')...");
        Message msg = obtainMessage(START_SEQUENCE, number);
        sendMessage(msg);
    }

    /**
     * Actual implementation of startEmergencyCallFromAirplaneModeSequence(),
     * guaranteed to run on the handler thread.
     * @see startEmergencyCallFromAirplaneModeSequence()
     */
    private void startSequenceInternal(Message msg) {
        if (DBG) log("startSequenceInternal(): msg = " + msg);

        // First of all, clean up any state (including mPartialWakeLock!)
        // left over from a prior emergency call sequence.
        // This ensures that we'll behave sanely if another
        // startEmergencyCallFromAirplaneModeSequence() comes in while
        // we're already in the middle of the sequence.
        cleanup();

        mNumber = (String) msg.obj;
        if (DBG) log("- startSequenceInternal: Got mNumber: '" + mNumber + "'");

        mNumRetriesSoFar = 0;

        // Reset mPhone to whatever the current default phone is right now.
        mPhone = mApp.mCM.getDefaultPhone();

        // Wake lock to make sure the processor doesn't go to sleep midway
        // through the emergency call sequence.
        PowerManager pm = (PowerManager) mApp.getSystemService(Context.POWER_SERVICE);
        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        // Acquire with a timeout, just to be sure we won't hold the wake
        // lock forever even if a logic bug (in this class) causes us to
        // somehow never call cleanup().
        if (DBG) log("- startSequenceInternal: acquiring wake lock");
        mPartialWakeLock.acquire(WAKE_LOCK_TIMEOUT);

        // No need to check the current service state here, since the only
        // reason the CallController would call this method in the first
        // place is if the radio is powered-off.
        //
        // So just go ahead and turn the radio on.

        powerOnRadio();  // We'll get an onServiceStateChanged() callback
                         // when the radio successfully comes up.

        // Next step: when the SERVICE_STATE_CHANGED event comes in,
        // we'll retry the call; see placeEmergencyCall();
        // But also, just in case, start a timer to make sure we'll retry
        // the call even if the SERVICE_STATE_CHANGED event never comes in
        // for some reason.
        startRetryTimer();

        // And finally, let the in-call UI know that we need to
        // display the "Turning on radio..." progress indication.
        mApp.inCallUiState.setProgressIndication(ProgressIndicationType.TURNING_ON_RADIO);

        // (Our caller is responsible for calling mApp.displayCallScreen().)
    }

    /**
     * Handles the SERVICE_STATE_CHANGED event.
     *
     * (Normally this event tells us that the radio has finally come
     * up.  In that case, it's now safe to actually place the
     * emergency call.)
     */
    private void onServiceStateChanged(Message msg) {
        ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result;
        if (DBG) log("onServiceStateChanged()...  new state = " + state);

        // Possible service states:
        // - STATE_IN_SERVICE        // Normal operation
        // - STATE_OUT_OF_SERVICE    // Still searching for an operator to register to,
        //                           // or no radio signal
        // - STATE_EMERGENCY_ONLY    // Phone is locked; only emergency numbers are allowed
        // - STATE_POWER_OFF         // Radio is explicitly powered off (airplane mode)

        // Once we reach either STATE_IN_SERVICE or STATE_EMERGENCY_ONLY,
        // it's finally OK to place the emergency call.
        boolean okToCall = (state.getState() == ServiceState.STATE_IN_SERVICE)
                || (state.getState() == ServiceState.STATE_EMERGENCY_ONLY);

        if (okToCall) {
            // Woo hoo!  It's OK to actually place the call.
            if (DBG) log("onServiceStateChanged: ok to call!");

            // Deregister for the service state change events.
            unregisterForServiceStateChanged();

            // Take down the "Turning on radio..." indication.
            mApp.inCallUiState.clearProgressIndication();

            placeEmergencyCall();

            // The in-call UI is probably still up at this point,
            // but make sure of that:
            mApp.displayCallScreen();
        } else {
            // The service state changed, but we're still not ready to call yet.
            // (This probably was the transition from STATE_POWER_OFF to
            // STATE_OUT_OF_SERVICE, which happens immediately after powering-on
            // the radio.)
            //
            // So just keep waiting; we'll probably get to either
            // STATE_IN_SERVICE or STATE_EMERGENCY_ONLY very shortly.
            // (Or even if that doesn't happen, we'll at least do another retry
            // when the RETRY_TIMEOUT event fires.)
            if (DBG) log("onServiceStateChanged: not ready to call yet, keep waiting...");
        }
    }

    /**
     * Handles a DISCONNECT event from the telephony layer.
     *
     * Even after we successfully place an emergency call (after powering
     * on the radio), it's still possible for the call to fail with the
     * disconnect cause OUT_OF_SERVICE.  If so, schedule a retry.
     */
    private void onDisconnect(Message msg) {
        Connection conn = (Connection) ((AsyncResult) msg.obj).result;
        Connection.DisconnectCause cause = conn.getDisconnectCause();
        if (DBG) log("onDisconnect: connection '" + conn
                     + "', addr '" + conn.getAddress() + "', cause = " + cause);

        if (cause == Connection.DisconnectCause.OUT_OF_SERVICE) {
            // Wait a bit more and try again (or just bail out totally if
            // we've had too many failures.)
            if (DBG) log("- onDisconnect: OUT_OF_SERVICE, need to retry...");
            scheduleRetryOrBailOut();
        } else {
            // Any other disconnect cause means we're done.
            // Either the emergency call succeeded *and* ended normally,
            // or else there was some error that we can't retry.  In either
            // case, just clean up our internal state.)

            if (DBG) log("==> Disconnect event; clean up...");
            cleanup();

            // Nothing else to do here.  If the InCallScreen was visible,
            // it would have received this disconnect event too (so it'll
            // show the "Call ended" state and finish itself without any
            // help from us.)
        }
    }

    /**
     * Handles the retry timer expiring.
     */
    private void onRetryTimeout() {
        PhoneConstants.State phoneState = mCM.getState();
        int serviceState = mPhone.getServiceState().getState();
        if (DBG) log("onRetryTimeout():  phone state " + phoneState
                     + ", service state " + serviceState
                     + ", mNumRetriesSoFar = " + mNumRetriesSoFar);

        // - If we're actually in a call, we've succeeded.
        //
        // - Otherwise, if the radio is now on, that means we successfully got
        //   out of airplane mode but somehow didn't get the service state
        //   change event.  In that case, try to place the call.
        //
        // - If the radio is still powered off, try powering it on again.

        if (phoneState == PhoneConstants.State.OFFHOOK) {
            if (DBG) log("- onRetryTimeout: Call is active!  Cleaning up...");
            cleanup();
            return;
        }

        if (serviceState != ServiceState.STATE_POWER_OFF) {
            // Woo hoo -- we successfully got out of airplane mode.

            // Deregister for the service state change events; we don't need
            // these any more now that the radio is powered-on.
            unregisterForServiceStateChanged();

            // Take down the "Turning on radio..." indication.
            mApp.inCallUiState.clearProgressIndication();

            placeEmergencyCall();  // If the call fails, placeEmergencyCall()
                                   // will schedule a retry.
        } else {
            // Uh oh; we've waited the full TIME_BETWEEN_RETRIES and the
            // radio is still not powered-on.  Try again...

            if (DBG) log("- Trying (again) to turn on the radio...");
            powerOnRadio();  // Again, we'll (hopefully) get an onServiceStateChanged()
                             // callback when the radio successfully comes up.

            // ...and also set a fresh retry timer (or just bail out
            // totally if we've had too many failures.)
            scheduleRetryOrBailOut();
        }

        // Finally, the in-call UI is probably still up at this point,
        // but make sure of that:
        mApp.displayCallScreen();
    }

    /**
     * Attempt to power on the radio (i.e. take the device out
     * of airplane mode.)
     *
     * Additionally, start listening for service state changes;
     * we'll eventually get an onServiceStateChanged() callback
     * when the radio successfully comes up.
     */
    private void powerOnRadio() {
        if (DBG) log("- powerOnRadio()...");

        // We're about to turn on the radio, so arrange to be notified
        // when the sequence is complete.
        registerForServiceStateChanged();

        // If airplane mode is on, we turn it off the same way that the
        // Settings activity turns it off.
        if (Settings.Global.getInt(mApp.getContentResolver(),
                                   Settings.Global.AIRPLANE_MODE_ON, 0) > 0) {
            if (DBG) log("==> Turning off airplane mode...");

            // Change the system setting
            Settings.Global.putInt(mApp.getContentResolver(),
                                   Settings.Global.AIRPLANE_MODE_ON, 0);

            // Post the intent
            Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            intent.putExtra("state", false);
            mApp.sendBroadcastAsUser(intent, UserHandle.ALL);
        } else {
            // Otherwise, for some strange reason the radio is off
            // (even though the Settings database doesn't think we're
            // in airplane mode.)  In this case just turn the radio
            // back on.
            if (DBG) log("==> (Apparently) not in airplane mode; manually powering radio on...");
            mPhone.setRadioPower(true);
        }
    }

    /**
     * Actually initiate the outgoing emergency call.
     * (We do this once the radio has successfully been powered-up.)
     *
     * If the call succeeds, we're done.
     * If the call fails, schedule a retry of the whole sequence.
     */
    private void placeEmergencyCall() {
        if (DBG) log("placeEmergencyCall()...");

        // Place an outgoing call to mNumber.
        // Note we call PhoneUtils.placeCall() directly; we don't want any
        // of the behavior from CallController.placeCallInternal() here.
        // (Specifically, we don't want to start the "emergency call from
        // airplane mode" sequence from the beginning again!)

        registerForDisconnect();  // Get notified when this call disconnects

        if (DBG) log("- placing call to '" + mNumber + "'...");
        int callStatus = PhoneUtils.placeCall(mApp,
                                              mPhone,
                                              mNumber,
                                              null,  // contactUri
                                              true,  // isEmergencyCall
                                              null);  // gatewayUri
        if (DBG) log("- PhoneUtils.placeCall() returned status = " + callStatus);

        boolean success;
        // Note PhoneUtils.placeCall() returns one of the CALL_STATUS_*
        // constants, not a CallStatusCode enum value.
        switch (callStatus) {
            case PhoneUtils.CALL_STATUS_DIALED:
                success = true;
                break;

            case PhoneUtils.CALL_STATUS_DIALED_MMI:
            case PhoneUtils.CALL_STATUS_FAILED:
            default:
                // Anything else is a failure, and we'll need to retry.
                Log.w(TAG, "placeEmergencyCall(): placeCall() failed: callStatus = " + callStatus);
                success = false;
                break;
        }

        if (success) {
            if (DBG) log("==> Success from PhoneUtils.placeCall()!");
            // Ok, the emergency call is (hopefully) under way.

            // We're not done yet, though, so don't call cleanup() here.
            // (It's still possible that this call will fail, and disconnect
            // with cause==OUT_OF_SERVICE.  If so, that will trigger a retry
            // from the onDisconnect() method.)
        } else {
            if (DBG) log("==> Failure.");
            // Wait a bit more and try again (or just bail out totally if
            // we've had too many failures.)
            scheduleRetryOrBailOut();
        }
    }

    /**
     * Schedules a retry in response to some failure (either the radio
     * failing to power on, or a failure when trying to place the call.)
     * Or, if we've hit the retry limit, bail out of this whole sequence
     * and display a failure message to the user.
     */
    private void scheduleRetryOrBailOut() {
        mNumRetriesSoFar++;
        if (DBG) log("scheduleRetryOrBailOut()...  mNumRetriesSoFar is now " + mNumRetriesSoFar);

        if (mNumRetriesSoFar > MAX_NUM_RETRIES) {
            Log.w(TAG, "scheduleRetryOrBailOut: hit MAX_NUM_RETRIES; giving up...");
            cleanup();
            // ...and have the InCallScreen display a generic failure
            // message.
            mApp.inCallUiState.setPendingCallStatusCode(CallStatusCode.CALL_FAILED);
        } else {
            if (DBG) log("- Scheduling another retry...");
            startRetryTimer();
            mApp.inCallUiState.setProgressIndication(ProgressIndicationType.RETRYING);
        }
    }

    /**
     * Clean up when done with the whole sequence: either after
     * successfully placing *and* ending the emergency call, or after
     * bailing out because of too many failures.
     *
     * The exact cleanup steps are:
     * - Take down any progress UI (and also ask the in-call UI to refresh itself,
     *   if it's still visible)
     * - Double-check that we're not still registered for any telephony events
     * - Clean up any extraneous handler messages (like retry timeouts) still in the queue
     * - Make sure we're not still holding any wake locks
     *
     * Basically this method guarantees that there will be no more
     * activity from the EmergencyCallHelper until the CallController
     * kicks off the whole sequence again with another call to
     * startEmergencyCallFromAirplaneModeSequence().
     *
     * Note we don't call this method simply after a successful call to
     * placeCall(), since it's still possible the call will disconnect
     * very quickly with an OUT_OF_SERVICE error.
     */
    private void cleanup() {
        if (DBG) log("cleanup()...");

        // Take down the "Turning on radio..." indication.
        mApp.inCallUiState.clearProgressIndication();

        unregisterForServiceStateChanged();
        unregisterForDisconnect();
        cancelRetryTimer();

        // Release / clean up the wake lock
        if (mPartialWakeLock != null) {
            if (mPartialWakeLock.isHeld()) {
                if (DBG) log("- releasing wake lock");
                mPartialWakeLock.release();
            }
            mPartialWakeLock = null;
        }

        // And finally, ask the in-call UI to refresh itself (to clean up the
        // progress indication if necessary), if it's currently visible.
        mApp.updateInCallScreen();
    }

    private void startRetryTimer() {
        removeMessages(RETRY_TIMEOUT);
        sendEmptyMessageDelayed(RETRY_TIMEOUT, TIME_BETWEEN_RETRIES);
    }

    private void cancelRetryTimer() {
        removeMessages(RETRY_TIMEOUT);
    }

    private void registerForServiceStateChanged() {
        // Unregister first, just to make sure we never register ourselves
        // twice.  (We need this because Phone.registerForServiceStateChanged()
        // does not prevent multiple registration of the same handler.)
        mPhone.unregisterForServiceStateChanged(this);  // Safe even if not currently registered
        mPhone.registerForServiceStateChanged(this, SERVICE_STATE_CHANGED, null);
    }

    private void unregisterForServiceStateChanged() {
        // This method is safe to call even if we haven't set mPhone yet.
        if (mPhone != null) {
            mPhone.unregisterForServiceStateChanged(this);  // Safe even if unnecessary
        }
        removeMessages(SERVICE_STATE_CHANGED);  // Clean up any pending messages too
    }

    private void registerForDisconnect() {
        // Note: no need to unregister first, since
        // CallManager.registerForDisconnect() automatically prevents
        // multiple registration of the same handler.
        mCM.registerForDisconnect(this, DISCONNECT, null);
    }

    private void unregisterForDisconnect() {
        mCM.unregisterForDisconnect(this);  // Safe even if not currently registered
        removeMessages(DISCONNECT);  // Clean up any pending messages too
    }


    //
    // Debugging
    //

    private static void log(String msg) {
        Log.d(TAG, msg);
    }
}
