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

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.telephony.AccessNetworkConstants;
import android.telephony.CellInfo;
import android.telephony.CellInfoLte;
import android.telephony.NetworkScan;
import android.telephony.NetworkScanRequest;
import android.telephony.RadioAccessSpecifier;
import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyScanManager;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Network Scan controller class which will scan for the specific bands as requested and
 * provide results to caller when ready.
 */
public class ANSNetworkScanCtlr {
    private static final String LOG_TAG = "ANSNetworkScanCtlr";
    private static final boolean DBG = true;
    private static final int SEARCH_PERIODICITY_SLOW = (int) TimeUnit.MINUTES.toSeconds(5);
    private static final int SEARCH_PERIODICITY_FAST = (int) TimeUnit.MINUTES.toSeconds(1);
    private static final int MAX_SEARCH_TIME = (int) TimeUnit.MINUTES.toSeconds(1);
    private final Object mLock = new Object();

    /* message  to handle scan responses from modem */
    private static final int MSG_SCAN_RESULTS_AVAILABLE = 1;
    private static final int MSG_SCAN_COMPLETE = 2;
    private static final int MSG_SCAN_ERROR = 3;

    /* scan object to keep track of current scan request */
    private NetworkScan mCurrentScan;
    private boolean mIsScanActive;
    private NetworkScanRequest mCurrentScanRequest;
    private List<String> mMccMncs;
    private TelephonyManager mTelephonyManager;
    @VisibleForTesting
    protected NetworkAvailableCallBack mNetworkAvailableCallBack;

    private Handler mHandler =  new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_SCAN_RESULTS_AVAILABLE:
                    logDebug("Msg received for scan results");
                    /* Todo: need to aggregate the results */
                    analyzeScanResults((List<CellInfo>) msg.obj);
                    break;
                case MSG_SCAN_COMPLETE:
                    logDebug("Msg received for scan complete");
                    restartScan();
                    break;
                case MSG_SCAN_ERROR:
                    logDebug("Msg received for scan error");
                    invalidateScanOnError((int) msg.obj);
                    break;
                default:
                    log("invalid message");
                    break;
            }
        }
    };

    @VisibleForTesting
    public TelephonyScanManager.NetworkScanCallback mNetworkScanCallback =
            new TelephonyScanManager.NetworkScanCallback() {

        @Override
        public void onResults(List<CellInfo> results) {
            logDebug("Total results :" + results.size());
            for (CellInfo cellInfo : results) {
                logDebug("cell info: " + cellInfo);
            }

            Message message = Message.obtain(mHandler, MSG_SCAN_RESULTS_AVAILABLE, results);
            message.sendToTarget();
        }

        @Override
        public void onComplete() {
            logDebug("Scan completed!");
            Message message = Message.obtain(mHandler, MSG_SCAN_COMPLETE, NetworkScan.SUCCESS);
            message.sendToTarget();
        }

        @Override
        public void onError(@NetworkScan.ScanErrorCode int error) {
            logDebug("Scan error " + error);
            Message message = Message.obtain(mHandler, MSG_SCAN_ERROR, error);
            message.sendToTarget();
        }
    };

    /**
     * call back for network availability
     */
    public interface NetworkAvailableCallBack {

        /**
         * Returns the scan results to the user, this callback will be called multiple times.
         */
        void onNetworkAvailability(List<CellInfo> results);

        /**
         * on error
         * @param error
         */
        void onError(int error);
    }


    /**
     * analyze scan results
     * @param results contains all available cells matching the scan request at current location.
     */
    public void analyzeScanResults(List<CellInfo> results) {
        /* Inform registrants about availability of network */
        if (mIsScanActive && results != null) {
            List<CellInfo> filteredResults = new ArrayList<CellInfo>();
            synchronized (mLock) {
                for (CellInfo cellInfo : results) {
                    if (mMccMncs.contains(getMccMnc(cellInfo))) {
                        filteredResults.add(cellInfo);
                    }
                }
            }

            if ((filteredResults.size() >= 1) && (mNetworkAvailableCallBack != null)) {
                /* Todo: change to aggregate results on success. */
                mNetworkAvailableCallBack.onNetworkAvailability(filteredResults);
            }
        }
    }

    private void invalidateScanOnError(int error) {
        logDebug("scan invalidated on error");
        if (mNetworkAvailableCallBack != null) {
            mNetworkAvailableCallBack.onError(error);
        }

        synchronized (mLock) {
            mIsScanActive = false;
            mCurrentScan = null;
        }
    }

    public ANSNetworkScanCtlr(Context c, TelephonyManager telephonyManager,
            NetworkAvailableCallBack networkAvailableCallBack) {
        init(c, telephonyManager, networkAvailableCallBack);
    }

    /**
     * initialize Network Scan controller
     * @param c context
     * @param telephonyManager Telephony manager instance
     * @param networkAvailableCallBack callback to be called when network selection is done
     */
    public void init(Context c, TelephonyManager telephonyManager,
            NetworkAvailableCallBack networkAvailableCallBack) {
        log("init called");
        mTelephonyManager = telephonyManager;
        mNetworkAvailableCallBack = networkAvailableCallBack;
    }

    /* get mcc mnc from cell info if the cell is for LTE */
    private String getMccMnc(CellInfo cellInfo) {
        if (cellInfo instanceof CellInfoLte) {
            return ((CellInfoLte) cellInfo).getCellIdentity().getMccString()
                    + ((CellInfoLte) cellInfo).getCellIdentity().getMncString();
        }

        return null;
    }

    private NetworkScanRequest createNetworkScanRequest(List<SubscriptionInfo> subscriptionInfos,
            int periodicity) {
        RadioAccessSpecifier[] ras = new RadioAccessSpecifier[1];
        int[] bands = new int[1];

        /* hardcoding band for now, Todo b/113753823 */
        bands[0] = AccessNetworkConstants.EutranBand.BAND_48;

        ArrayList<String> mccMncs = new ArrayList<String>();
        /* retrieve mcc mncs for a subscription id */
        for (SubscriptionInfo subscriptionInfo : subscriptionInfos) {
            mccMncs.add(subscriptionInfo.getMccString() + subscriptionInfo.getMncString());
        }

        /* create network scan request */
        ras[0] = new RadioAccessSpecifier(AccessNetworkConstants.AccessNetworkType.EUTRAN, bands,
                null);
        NetworkScanRequest networkScanRequest = new NetworkScanRequest(
                NetworkScanRequest.SCAN_TYPE_PERIODIC, ras, periodicity, MAX_SEARCH_TIME, false,
                NetworkScanRequest.MAX_INCREMENTAL_PERIODICITY_SEC, mccMncs);
        synchronized (mLock) {
            mMccMncs = mccMncs;
        }
        return networkScanRequest;
    }

    /**
     * start high interval network scan
     * @param subscriptionInfos list of subscriptions for which the scanning needs to be started.
     * @return true if successfully accepted request.
     */
    public boolean startSlowNetworkScan(List<SubscriptionInfo> subscriptionInfos) {
        NetworkScanRequest networkScanRequest = createNetworkScanRequest(subscriptionInfos,
                SEARCH_PERIODICITY_SLOW);
        return startNetworkScan(networkScanRequest);
    }

    /**
     * start less interval network scan
     * @param subscriptionInfos list of subscriptions for which the scanning needs to be started.
     * @return true if successfully accepted request.
     */
    public boolean startFastNetworkScan(List<SubscriptionInfo> subscriptionInfos) {
        NetworkScanRequest networkScanRequest = createNetworkScanRequest(subscriptionInfos,
                SEARCH_PERIODICITY_FAST);
        return startNetworkScan(networkScanRequest);
    }


    private boolean startNetworkScan(NetworkScanRequest networkScanRequest) {
        NetworkScan networkScan;
        synchronized (mLock) {
            /* if the request is same as existing one, then make sure to not proceed */
            if (mIsScanActive && mCurrentScanRequest.equals(networkScanRequest)) {
                return true;
            }

            /* Need to stop current scan if we already have one */
            stopNetworkScan();

            /* start new scan */
            networkScan = mTelephonyManager.requestNetworkScan(networkScanRequest,
                    mNetworkScanCallback);

            mCurrentScan = networkScan;
            mIsScanActive = true;
            mCurrentScanRequest = networkScanRequest;
        }

        logDebug("startNetworkScan " + networkScanRequest);
        return true;
    }

    private void restartScan() {
        NetworkScan networkScan;
        synchronized (mLock) {
            if (mCurrentScanRequest != null) {
                networkScan = mTelephonyManager.requestNetworkScan(mCurrentScanRequest,
                        mNetworkScanCallback);
                mIsScanActive = true;
            }
        }
    }

    /**
     * stop network scan
     */
    public void stopNetworkScan() {
        logDebug("stopNetworkScan");
        synchronized (mLock) {
            if (mIsScanActive && mCurrentScan != null) {
                try {
                    mCurrentScan.stopScan();
                } catch (IllegalArgumentException iae) {
                    logDebug("Scan failed with exception " + iae);
                }
                mIsScanActive = false;
                mCurrentScan = null;
                mCurrentScanRequest = null;
            }
        }
    }

    private static void log(String msg) {
        Rlog.d(LOG_TAG, msg);
    }

    private static void logDebug(String msg) {
        if (DBG) {
            Rlog.d(LOG_TAG, msg);
        }
    }
}
