/*
 * 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.bluetooth.hfp;

import android.content.Context;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.util.Log;
import android.bluetooth.BluetoothDevice;


// Note:
// All methods in this class are not thread safe, donot call them from
// multiple threads. Call them from the HeadsetPhoneStateMachine message
// handler only.
class HeadsetPhoneState {
    private static final String TAG = "HeadsetPhoneState";

    private HeadsetStateMachine mStateMachine;
    private TelephonyManager mTelephonyManager;
    private ServiceState mServiceState;

    // HFP 1.6 CIND service
    private int mService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE;

    // Number of active (foreground) calls
    private int mNumActive = 0;

    // Current Call Setup State
    private int mCallState = HeadsetHalConstants.CALL_STATE_IDLE;

    // Number of held (background) calls
    private int mNumHeld = 0;

    // HFP 1.6 CIND signal
    private int mSignal = 0;

    // HFP 1.6 CIND roam
    private int mRoam = HeadsetHalConstants.SERVICE_TYPE_HOME;

    // HFP 1.6 CIND battchg
    private int mBatteryCharge = 0;

    private int mSpeakerVolume = 0;

    private int mMicVolume = 0;

    private boolean mListening = false;

    // when HFP Service Level Connection is established
    private boolean mSlcReady = false;

    private Context mContext = null;

    private PhoneStateListener mPhoneStateListener = null;

    private SubscriptionManager mSubMgr;

    private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
            new OnSubscriptionsChangedListener() {
        @Override
        public void onSubscriptionsChanged() {
            listenForPhoneState(false);
            listenForPhoneState(true);
        }
    };


    HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) {
        mStateMachine = stateMachine;
        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        mContext = context;

        // Register for SubscriptionInfo list changes which is guaranteed
        // to invoke onSubscriptionInfoChanged and which in turns calls
        // loadInBackgroud.
        mSubMgr = SubscriptionManager.from(mContext);
        mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
    }

    public void cleanup() {
        listenForPhoneState(false);
        mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);

        mTelephonyManager = null;
        mStateMachine = null;
    }

    void listenForPhoneState(boolean start) {

        mSlcReady = start;

        if (start) {
            startListenForPhoneState();
        } else {
            stopListenForPhoneState();
        }

    }

    private void startListenForPhoneState() {
        if (!mListening && mSlcReady && mTelephonyManager != null) {

            int subId = SubscriptionManager.getDefaultSubscriptionId();

            if (SubscriptionManager.isValidSubscriptionId(subId)) {
                mPhoneStateListener = getPhoneStateListener(subId);

                mTelephonyManager.listen(mPhoneStateListener,
                                         PhoneStateListener.LISTEN_SERVICE_STATE |
                                         PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
                mListening = true;
            }
        }
    }

    private void stopListenForPhoneState() {
        if (mListening && mTelephonyManager != null) {

            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
            mListening = false;
        }
    }

    int getService() {
        return mService;
    }

    int getNumActiveCall() {
        return mNumActive;
    }

    void setNumActiveCall(int numActive) {
        mNumActive = numActive;
    }

    int getCallState() {
        return mCallState;
    }

    void setCallState(int callState) {
        mCallState = callState;
    }

    int getNumHeldCall() {
        return mNumHeld;
    }

    void setNumHeldCall(int numHeldCall) {
        mNumHeld = numHeldCall;
    }

    int getSignal() {
        return mSignal;
    }

    int getRoam() {
        return mRoam;
    }

    void setRoam(int roam) {
        if (mRoam != roam) {
            mRoam = roam;
            sendDeviceStateChanged();
        }
    }

    void setBatteryCharge(int batteryLevel) {
        if (mBatteryCharge != batteryLevel) {
            mBatteryCharge = batteryLevel;
            sendDeviceStateChanged();
        }
    }

    int getBatteryCharge() {
        return mBatteryCharge;
    }

    void setSpeakerVolume(int volume) {
        mSpeakerVolume = volume;
    }

    int getSpeakerVolume() {
        return mSpeakerVolume;
    }

    void setMicVolume(int volume) {
        mMicVolume = volume;
    }

    int getMicVolume() {
        return mMicVolume;
    }

    boolean isInCall() {
        return (mNumActive >= 1);
    }

    void sendDeviceStateChanged()
    {
        // When out of service, send signal strength as 0. Some devices don't
        // use the service indicator, but only the signal indicator
        int signal = mService == HeadsetHalConstants.NETWORK_STATE_AVAILABLE ? mSignal : 0;

        Log.d(TAG, "sendDeviceStateChanged. mService="+ mService +
                   " mSignal=" + signal +" mRoam="+ mRoam +
                   " mBatteryCharge=" + mBatteryCharge);
        HeadsetStateMachine sm = mStateMachine;
        if (sm != null) {
            sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED,
                new HeadsetDeviceState(mService, mRoam, signal, mBatteryCharge));
        }
    }

    private PhoneStateListener getPhoneStateListener(int subId) {
        PhoneStateListener mPhoneStateListener = new PhoneStateListener(subId) {
            @Override
            public void onServiceStateChanged(ServiceState serviceState) {

                mServiceState = serviceState;
                mService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ?
                    HeadsetHalConstants.NETWORK_STATE_AVAILABLE :
                    HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE;
                setRoam(serviceState.getRoaming() ? HeadsetHalConstants.SERVICE_TYPE_ROAMING
                                                  : HeadsetHalConstants.SERVICE_TYPE_HOME);

                sendDeviceStateChanged();
            }

            @Override
            public void onSignalStrengthsChanged(SignalStrength signalStrength) {

                int prevSignal = mSignal;
                if (mService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) {
                    mSignal = 0;
                } else if (signalStrength.isGsm()) {
                    mSignal = signalStrength.getLteLevel();
                    if (mSignal == SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
                        mSignal = gsmAsuToSignal(signalStrength);
                    } else {
                        // SignalStrength#getLteLevel returns the scale from 0-4
                        // Bluetooth signal scales at 0-5
                        // Let's match up the larger side
                        mSignal++;
                    }
                } else {
                    mSignal = cdmaDbmEcioToSignal(signalStrength);
                }

                // network signal strength is scaled to BT 1-5 levels.
                // This results in a lot of duplicate messages, hence this check
                if (prevSignal != mSignal) {
                    sendDeviceStateChanged();
                }
            }

            /* convert [0,31] ASU signal strength to the [0,5] expected by
             * bluetooth devices. Scale is similar to status bar policy
             */
            private int gsmAsuToSignal(SignalStrength signalStrength) {
                int asu = signalStrength.getGsmSignalStrength();
                if      (asu >= 16) return 5;
                else if (asu >= 8)  return 4;
                else if (asu >= 4)  return 3;
                else if (asu >= 2)  return 2;
                else if (asu >= 1)  return 1;
                else                return 0;
            }

            /**
             * Convert the cdma / evdo db levels to appropriate icon level.
             * The scale is similar to the one used in status bar policy.
             *
             * @param signalStrength
             * @return the icon level
             */
            private int cdmaDbmEcioToSignal(SignalStrength signalStrength) {
                int levelDbm = 0;
                int levelEcio = 0;
                int cdmaIconLevel = 0;
                int evdoIconLevel = 0;
                int cdmaDbm = signalStrength.getCdmaDbm();
                int cdmaEcio = signalStrength.getCdmaEcio();

                if (cdmaDbm >= -75) levelDbm = 4;
                else if (cdmaDbm >= -85) levelDbm = 3;
                else if (cdmaDbm >= -95) levelDbm = 2;
                else if (cdmaDbm >= -100) levelDbm = 1;
                else levelDbm = 0;

                // Ec/Io are in dB*10
                if (cdmaEcio >= -90) levelEcio = 4;
                else if (cdmaEcio >= -110) levelEcio = 3;
                else if (cdmaEcio >= -130) levelEcio = 2;
                else if (cdmaEcio >= -150) levelEcio = 1;
                else levelEcio = 0;

                cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio;

                // STOPSHIP: Change back to getRilVoiceRadioTechnology
                if (mServiceState != null &&
                      (mServiceState.getRadioTechnology() ==
                          ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 ||
                       mServiceState.getRadioTechnology() ==
                           ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) {
                      int evdoEcio = signalStrength.getEvdoEcio();
                      int evdoSnr = signalStrength.getEvdoSnr();
                      int levelEvdoEcio = 0;
                      int levelEvdoSnr = 0;

                      // Ec/Io are in dB*10
                      if (evdoEcio >= -650) levelEvdoEcio = 4;
                      else if (evdoEcio >= -750) levelEvdoEcio = 3;
                      else if (evdoEcio >= -900) levelEvdoEcio = 2;
                      else if (evdoEcio >= -1050) levelEvdoEcio = 1;
                      else levelEvdoEcio = 0;

                      if (evdoSnr > 7) levelEvdoSnr = 4;
                      else if (evdoSnr > 5) levelEvdoSnr = 3;
                      else if (evdoSnr > 3) levelEvdoSnr = 2;
                      else if (evdoSnr > 1) levelEvdoSnr = 1;
                      else levelEvdoSnr = 0;

                      evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr;
                }
                // TODO(): There is a bug open regarding what should be sent.
                return (cdmaIconLevel > evdoIconLevel) ?  cdmaIconLevel : evdoIconLevel;
            }
        };
        return mPhoneStateListener;
    }

}

class HeadsetDeviceState {
    int mService;
    int mRoam;
    int mSignal;
    int mBatteryCharge;

    HeadsetDeviceState(int service, int roam, int signal, int batteryCharge) {
        mService = service;
        mRoam = roam;
        mSignal = signal;
        mBatteryCharge = batteryCharge;
    }
}

class HeadsetCallState {
    int mNumActive;
    int mNumHeld;
    int mCallState;
    String mNumber;
    int mType;

    public HeadsetCallState(int numActive, int numHeld, int callState, String number, int type) {
        mNumActive = numActive;
        mNumHeld = numHeld;
        mCallState = callState;
        mNumber = number;
        mType = type;
    }
}

class HeadsetClccResponse {
    int mIndex;
    int mDirection;
    int mStatus;
    int mMode;
    boolean mMpty;
    String mNumber;
    int mType;

    public HeadsetClccResponse(int index, int direction, int status, int mode, boolean mpty,
                               String number, int type) {
        mIndex = index;
        mDirection = direction;
        mStatus = status;
        mMode = mode;
        mMpty = mpty;
        mNumber = number;
        mType = type;
    }
}

class HeadsetVendorSpecificResultCode {
    BluetoothDevice mDevice;
    String mCommand;
    String mArg;

    public HeadsetVendorSpecificResultCode(BluetoothDevice device, String command, String arg) {
        mDevice = device;
        mCommand = command;
        mArg = arg;
    }
}
