/*
 * Copyright (C) 2013 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.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.telephony.ServiceState;
import android.util.Log;

import com.android.internal.telephony.Phone;
import com.google.common.base.Preconditions;

/**
 * Starts and displays status for Hands Free Activation (HFA).
 *
 * This class operates with Hands Free Activation apps.
 * It starts by broadcasting the intent com.android.action.START_HFA.
 * An HFA app will pick that up and start the HFA process.
 * If it fails it return ERROR_HFA Intent and upon success returns COMPLETE_HFA.
 *
 * If successful, we bounce the radio so that the service picks up the new number.
 * Once the radio is back on we callback the requestor.
 *
 * If there is an error, we do not bounce the radio but still callback with a failure.
 *
 * TODO(klp): We need system-only permissions for the HFA intents.
 */
public class HfaLogic {
    private static final String TAG = HfaLogic.class.getSimpleName();

    private static final String ACTION_START = "com.android.action.START_HFA";
    private static final String ACTION_ERROR = "com.android.action.ERROR_HFA";
    private static final String ACTION_CANCEL = "com.android.action.CANCEL_HFA";
    private static final String ACTION_COMPLETE = "com.android.action.COMPLETE_HFA";

    private static final int SERVICE_STATE_CHANGED = 1;

    public static final int NOT_WAITING = 0;
    public static final int WAITING_FOR_RADIO_OFF = 1;
    public static final int WAITING_FOR_RADIO_ON = 2;

    public static final int OTASP_UNKNOWN = 0;
    public static final int OTASP_USER_SKIPPED = 1;
    public static final int OTASP_SUCCESS = 2;
    public static final int OTASP_FAILURE = 3;

    private int mPhoneMonitorState = NOT_WAITING;
    private BroadcastReceiver mReceiver;
    private HfaLogicCallback mCallback;
    private PendingIntent mResponseIntent;
    private Context mContext;

    // No retry at the moment. Increase later if necessary.
    private static final int DEFAULT_RETRY_COUNT = 0;
    private int mRetryCount;

    public interface HfaLogicCallback {
        public void onSuccess();
        public void onError(String errorMsg);
    }

    public HfaLogic(Context context, HfaLogicCallback callback, PendingIntent intent) {
        mCallback = Preconditions.checkNotNull(callback);
        mContext = Preconditions.checkNotNull(context);
        mResponseIntent = intent;
    }

    public void start() {
        Log.i(TAG, "start:");
        mRetryCount = DEFAULT_RETRY_COUNT;
        startHfaIntentReceiver();
        startProvisioning();
    }

    private void startProvisioning() {
        Log.i(TAG, "startProvisioning:");
        sendHfaCommand(ACTION_START);
    }

    private void sendHfaCommand(String action) {
        Log.i(TAG, "sendHfaCommand: command=" + action);
        mContext.sendBroadcast(new Intent(action));
    }

    private void onHfaError(String errorMsg) {
        Log.i(TAG, "onHfaError: call mCallBack.onError errorMsg=" + errorMsg
                + " mRetryCount=" + mRetryCount);
        mRetryCount -= 1;
        if (mRetryCount >= 0) {
            Log.i(TAG, "onHfaError: retry");
            startProvisioning();
        } else {
            Log.i(TAG, "onHfaError: Declare OTASP_FAILURE");
            mRetryCount = 0;
            stopHfaIntentReceiver();
            sendFinalResponse(OTASP_FAILURE, errorMsg);
            mCallback.onError(errorMsg);
        }
    }

    private void onHfaSuccess() {
        Log.i(TAG, "onHfaSuccess: NOT bouncing radio call onTotalSuccess");
        stopHfaIntentReceiver();
        // bounceRadio();
        onTotalSuccess();
    }

    private void onTotalSuccess() {
        Log.i(TAG, "onTotalSuccess: call mCallBack.onSuccess");
        sendFinalResponse(OTASP_SUCCESS, null);
        mCallback.onSuccess();
    }

    private void bounceRadio() {
        final Phone phone = PhoneGlobals.getInstance().getPhone();
        phone.registerForServiceStateChanged(mHandler, SERVICE_STATE_CHANGED, null);

        mPhoneMonitorState = WAITING_FOR_RADIO_OFF;
        phone.setRadioPower(false);
        onServiceStateChange(phone.getServiceState());
    }

    private void onServiceStateChange(ServiceState state) {
        final boolean radioIsOff = state.getVoiceRegState() == ServiceState.STATE_POWER_OFF;
        final Phone phone = PhoneGlobals.getInstance().getPhone();

        Log.i(TAG, "Radio is on: " + !radioIsOff);

        if (mPhoneMonitorState == WAITING_FOR_RADIO_OFF) {
            if (radioIsOff) {
                mPhoneMonitorState = WAITING_FOR_RADIO_ON;
                phone.setRadioPower(true);
            }
        } else if (mPhoneMonitorState == WAITING_FOR_RADIO_ON) {
            if (!radioIsOff) {
                mPhoneMonitorState = NOT_WAITING;
                phone.unregisterForServiceStateChanged(mHandler);

                onTotalSuccess();
            }
        }
    }

    private void startHfaIntentReceiver() {
        final IntentFilter filter = new IntentFilter(ACTION_COMPLETE);
        filter.addAction(ACTION_ERROR);

        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
                if (action.equals(ACTION_ERROR)) {
                    onHfaError(intent.getStringExtra("errorCode"));
                } else if (action.equals(ACTION_COMPLETE)) {
                    Log.i(TAG, "Hfa Successful");
                    onHfaSuccess();
                }
            }
        };

        mContext.registerReceiver(mReceiver, filter);
    }

    private void stopHfaIntentReceiver() {
        if (mReceiver != null) {
            mContext.unregisterReceiver(mReceiver);
            mReceiver = null;
        }
    }

    private void sendFinalResponse(int responseCode, String errorCode) {
        if (mResponseIntent != null) {
            final Intent extraStuff = new Intent();
            extraStuff.putExtra(OtaUtils.EXTRA_OTASP_RESULT_CODE, responseCode);

            if (responseCode == OTASP_FAILURE && errorCode != null) {
                extraStuff.putExtra(OtaUtils.EXTRA_OTASP_ERROR_CODE, errorCode);
            }

            try {
                Log.i(TAG, "Sending OTASP confirmation with result code: "
                        + responseCode);
                mResponseIntent.send(mContext, 0 /* resultCode (not used) */, extraStuff);
            } catch (CanceledException e) {
                Log.e(TAG, "Pending Intent canceled");
            }
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SERVICE_STATE_CHANGED:
                    ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result;
                    onServiceStateChange(state);
                    break;
                default:
                    break;
            }
        }
    };

}
