/*
 * Copyright (C) 2016 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.server.emergency;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.telephony.CellInfo;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;

import com.android.server.SystemService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * A service that listens to connectivity and SIM card changes and determines if the emergency mode
 * should be enabled
 */
public class EmergencyAffordanceService extends SystemService {

    private static final String TAG = "EmergencyAffordanceService";

    private static final int NUM_SCANS_UNTIL_ABORT = 4;

    private static final int INITIALIZE_STATE = 1;
    private static final int CELL_INFO_STATE_CHANGED = 2;
    private static final int SUBSCRIPTION_CHANGED = 3;

    /**
     * Global setting, whether the last scan of the sim cards reveal that a sim was inserted that
     * requires the emergency affordance. The value is a boolean (1 or 0).
     * @hide
     */
    private static final String EMERGENCY_SIM_INSERTED_SETTING = "emergency_sim_inserted_before";

    private final Context mContext;
    private final ArrayList<Integer> mEmergencyCallMccNumbers;

    private final Object mLock = new Object();

    private TelephonyManager mTelephonyManager;
    private SubscriptionManager mSubscriptionManager;
    private boolean mEmergencyAffordanceNeeded;
    private MyHandler mHandler;
    private int mScansCompleted;
    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
        @Override
        public void onCellInfoChanged(List<CellInfo> cellInfo) {
            if (!isEmergencyAffordanceNeeded()) {
                requestCellScan();
            }
        }

        @Override
        public void onCellLocationChanged(CellLocation location) {
            if (!isEmergencyAffordanceNeeded()) {
                requestCellScan();
            }
        }
    };
    private BroadcastReceiver mAirplaneModeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Settings.Global.getInt(context.getContentResolver(),
                    Settings.Global.AIRPLANE_MODE_ON, 0) == 0) {
                startScanning();
                requestCellScan();
            }
        }
    };
    private boolean mSimNeedsEmergencyAffordance;
    private boolean mNetworkNeedsEmergencyAffordance;
    private boolean mVoiceCapable;

    private void requestCellScan() {
        mHandler.obtainMessage(CELL_INFO_STATE_CHANGED).sendToTarget();
    }

    private SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionChangedListener
            = new SubscriptionManager.OnSubscriptionsChangedListener() {
        @Override
        public void onSubscriptionsChanged() {
            mHandler.obtainMessage(SUBSCRIPTION_CHANGED).sendToTarget();
        }
    };

    public EmergencyAffordanceService(Context context) {
        super(context);
        mContext = context;
        int[] numbers = context.getResources().getIntArray(
                com.android.internal.R.array.config_emergency_mcc_codes);
        mEmergencyCallMccNumbers = new ArrayList<>(numbers.length);
        for (int i = 0; i < numbers.length; i++) {
            mEmergencyCallMccNumbers.add(numbers[i]);
        }
    }

    private void updateEmergencyAffordanceNeeded() {
        synchronized (mLock) {
            mEmergencyAffordanceNeeded = mVoiceCapable && (mSimNeedsEmergencyAffordance ||
                    mNetworkNeedsEmergencyAffordance);
            Settings.Global.putInt(mContext.getContentResolver(),
                    Settings.Global.EMERGENCY_AFFORDANCE_NEEDED,
                    mEmergencyAffordanceNeeded ? 1 : 0);
            if (mEmergencyAffordanceNeeded) {
                stopScanning();
            }
        }
    }

    private void stopScanning() {
        synchronized (mLock) {
            mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
            mScansCompleted = 0;
        }
    }

    private boolean isEmergencyAffordanceNeeded() {
        synchronized (mLock) {
            return mEmergencyAffordanceNeeded;
        }
    }

    @Override
    public void onStart() {
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
            mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
            mVoiceCapable = mTelephonyManager.isVoiceCapable();
            if (!mVoiceCapable) {
                updateEmergencyAffordanceNeeded();
                return;
            }
            mSubscriptionManager = SubscriptionManager.from(mContext);
            HandlerThread thread = new HandlerThread(TAG);
            thread.start();
            mHandler = new MyHandler(thread.getLooper());
            mHandler.obtainMessage(INITIALIZE_STATE).sendToTarget();
            startScanning();
            IntentFilter filter = new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
            mContext.registerReceiver(mAirplaneModeReceiver, filter);
            mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionChangedListener);
        }
    }

    private void startScanning() {
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CELL_INFO
                | PhoneStateListener.LISTEN_CELL_LOCATION);
    }

    /** Handler to do the heavier work on */
    private class MyHandler extends Handler {

        public MyHandler(Looper l) {
            super(l);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case INITIALIZE_STATE:
                    handleInitializeState();
                    break;
                case CELL_INFO_STATE_CHANGED:
                    handleUpdateCellInfo();
                    break;
                case SUBSCRIPTION_CHANGED:
                    handleUpdateSimSubscriptionInfo();
                    break;
            }
        }
    }

    private void handleInitializeState() {
        if (handleUpdateSimSubscriptionInfo()) {
            return;
        }
        if (handleUpdateCellInfo()) {
            return;
        }
        updateEmergencyAffordanceNeeded();
    }

    private boolean handleUpdateSimSubscriptionInfo() {
        boolean neededBefore = simNeededAffordanceBefore();
        boolean neededNow = neededBefore;
        List<SubscriptionInfo> activeSubscriptionInfoList =
                mSubscriptionManager.getActiveSubscriptionInfoList();
        if (activeSubscriptionInfoList == null) {
            setSimNeedsEmergencyAffordance(neededNow);
            return neededNow;
        }
        for (SubscriptionInfo info : activeSubscriptionInfoList) {
            int mcc = info.getMcc();
            if (mccRequiresEmergencyAffordance(mcc)) {
                neededNow = true;
                break;
            } else if (mcc != 0 && mcc != Integer.MAX_VALUE){
                // a Sim with a different mcc code was found
                neededNow = false;
            }
            String simOperator = mTelephonyManager
                    .createForSubscriptionId(info.getSubscriptionId()).getSimOperator();
            mcc = 0;
            if (simOperator != null && simOperator.length() >= 3) {
                mcc = Integer.parseInt(simOperator.substring(0, 3));
            }
            if (mcc != 0) {
                if (mccRequiresEmergencyAffordance(mcc)) {
                    neededNow = true;
                    break;
                } else {
                    // a Sim with a different mcc code was found
                    neededNow = false;
                }
            }
        }
        setSimNeedsEmergencyAffordance(neededNow);
        return neededNow;
    }

    private void setSimNeedsEmergencyAffordance(boolean simNeedsEmergencyAffordance) {
        if (simNeededAffordanceBefore() != simNeedsEmergencyAffordance) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    EMERGENCY_SIM_INSERTED_SETTING,
                    simNeedsEmergencyAffordance ? 1 : 0);
        }
        if (simNeedsEmergencyAffordance != mSimNeedsEmergencyAffordance) {
            mSimNeedsEmergencyAffordance = simNeedsEmergencyAffordance;
            updateEmergencyAffordanceNeeded();
        }
    }

    private boolean simNeededAffordanceBefore() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                EMERGENCY_SIM_INSERTED_SETTING, 0) != 0;
    }

    private boolean handleUpdateCellInfo() {
        List<CellInfo> cellInfos = mTelephonyManager.getAllCellInfo();
        if (cellInfos == null) {
            return false;
        }
        boolean stopScanningAfterScan = false;
        for (CellInfo cellInfo : cellInfos) {
            int mcc = 0;
            if (cellInfo instanceof CellInfoGsm) {
                mcc = ((CellInfoGsm) cellInfo).getCellIdentity().getMcc();
            } else if (cellInfo instanceof CellInfoLte) {
                mcc = ((CellInfoLte) cellInfo).getCellIdentity().getMcc();
            } else if (cellInfo instanceof CellInfoWcdma) {
                mcc = ((CellInfoWcdma) cellInfo).getCellIdentity().getMcc();
            }
            if (mccRequiresEmergencyAffordance(mcc)) {
                setNetworkNeedsEmergencyAffordance(true);
                return true;
            } else if (mcc != 0 && mcc != Integer.MAX_VALUE) {
                // we found an mcc that isn't in the list, abort
                stopScanningAfterScan = true;
            }
        }
        if (stopScanningAfterScan) {
            stopScanning();
        } else {
            onCellScanFinishedUnsuccessful();
        }
        setNetworkNeedsEmergencyAffordance(false);
        return false;
    }

    private void setNetworkNeedsEmergencyAffordance(boolean needsAffordance) {
        synchronized (mLock) {
            mNetworkNeedsEmergencyAffordance = needsAffordance;
            updateEmergencyAffordanceNeeded();
        }
    }

    private void onCellScanFinishedUnsuccessful() {
        synchronized (mLock) {
            mScansCompleted++;
            if (mScansCompleted >= NUM_SCANS_UNTIL_ABORT) {
                stopScanning();
            }
        }
    }

    private boolean mccRequiresEmergencyAffordance(int mcc) {
        return mEmergencyCallMccNumbers.contains(mcc);
    }
}
