/*
 * Copyright (C) 2020 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.internal.telephony.vendor.dataconnection;

import android.app.AlertDialog;
import android.telephony.AccessNetworkConstants;
import android.telephony.DataFailCause;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.view.WindowManager;

import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.dataconnection.ApnContext;
import com.android.internal.telephony.dataconnection.DcTracker;

import java.util.HashSet;
import java.util.Iterator;

public class VendorDcTracker extends DcTracker {
    private String LOG_TAG = "VendorDCT";
    private HashSet<String> mIccidSet = new HashSet<String>();
    private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;

    // Maximum data reject count
    public static final int MAX_PDP_REJECT_COUNT = 3;

    // Data reset event tracker to know reset events.
    private VendorDataResetEventTracker mVendorDataResetEventTracker = null;

    // data reject dialog, made static because only one dialog object can be
    // used between multiple dataconnection objects.
    protected static AlertDialog mDataRejectDialog = null;

    //Store data reject cause for comparison
    private String mDataRejectReason = "NONE";

    //Store data reject count
    private int mDataRejectCount = 0;

    //Store data reject cause code
    private int mPdpRejectCauseCode = 0;

    // Constructor
    public VendorDcTracker(Phone phone, int transportType) {
        super(phone, transportType);
        mTransportType = transportType;
        LOG_TAG = LOG_TAG + "-" +
                ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) ? "C" : "I");
        if (DBG) log(LOG_TAG + ".constructor");
        fillIccIdSet();
    }

    @Override
    protected boolean allowInitialAttachForOperator() {
        String iccId = mPhone.getIccSerialNumber();
        if (iccId != null) {
            Iterator<String> itr = mIccidSet.iterator();
            while (itr.hasNext()) {
                if (iccId.contains(itr.next())) {
                    return false;
                }
            }
        }
        return true;
    }

    private void fillIccIdSet() {
        mIccidSet.add("8991840");
        mIccidSet.add("8991854");
        mIccidSet.add("8991855");
        mIccidSet.add("8991856");
        mIccidSet.add("8991857");
        mIccidSet.add("8991858");
        mIccidSet.add("8991859");
        mIccidSet.add("899186");
        mIccidSet.add("8991870");
        mIccidSet.add("8991871");
        mIccidSet.add("8991872");
        mIccidSet.add("8991873");
        mIccidSet.add("8991874");
    }

    @Override
    protected void onVoiceCallEnded() {
        if (DBG) log("onVoiceCallEnded");
        mInVoiceCall = false;
        if (isAnyDataConnected()) {
            if (!mPhone.getServiceStateTracker().isConcurrentVoiceAndDataAllowed()) {
                startNetStatPoll();
                startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
                mPhone.notifyAllActiveDataConnections();
            } else {
                // clean slate after call end.
                resetPollStats();
            }
        }
        //Allow data call retry only on DDS sub
        if (mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId()) {
            // reset reconnect timer
            setupDataOnAllConnectableApns(Phone.REASON_VOICE_CALL_ENDED, RetryFailures.ALWAYS);

        }
    }

    @Override
    protected void setupDataOnConnectableApn(ApnContext apnContext, String reason,
            RetryFailures retryFailures) {
        if (mPhone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_pdp_reject_enable_retry) &&
                mDataRejectCount > 0) {
            log("setupDataOnConnectableApn: data retry in progress, skip processing");
        } else {
            super.setupDataOnConnectableApn(apnContext, reason, retryFailures);
        }
    }

    @Override
    protected void onDataSetupComplete(ApnContext apnContext, boolean success, int cause,
            @RequestNetworkType int requestType) {
        boolean isPdpRejectConfigEnabled = mPhone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_pdp_reject_enable_retry);
        if (success) {
            if (isPdpRejectConfigEnabled) {
                handlePdpRejectCauseSuccess();
            }
        } else {
            mPdpRejectCauseCode = cause;
        }

        super.onDataSetupComplete(apnContext, success, cause, requestType);
    }

    @Override
    protected void onDataSetupCompleteError(ApnContext apnContext,
            @RequestNetworkType int requestType) {
        long delay = apnContext.getDelayForNextApn(mFailFast);
        if (mPhone.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_pdp_reject_enable_retry)) {
            String reason = DataFailCause.toString(mPdpRejectCauseCode);

            if (isMatchingPdpRejectCause(reason)) {
                if (mVendorDataResetEventTracker == null) {
                    mVendorDataResetEventTracker = new VendorDataResetEventTracker(mTransportType,
                            mPhone, mResetEventListener);
                }
                if (mDataRejectCount == 0) {
                    mVendorDataResetEventTracker.startResetEventTracker();
                }
                boolean isHandled = handlePdpRejectCauseFailure(reason);

                /* If MAX Reject count reached, display pop-up to user */
                if (MAX_PDP_REJECT_COUNT <= mDataRejectCount) {
                    if (DBG) log("onDataSetupCompleteError: reached max retry count");
                    displayPopup(mDataRejectReason);
                    delay = -1;
                } else if (isHandled) {
                    delay = mPhone.getContext().getResources().getInteger(
                            com.android.internal.R.integer.config_pdp_reject_retry_delay_ms);
                    if (DBG) log("onDataSetupCompleteError: delay from config: " + delay);
                }
            } else {
                if (DBG) log("onDataSetupCompleteError: reset reject count");
                resetDataRejectCounter();
            }
        }

        // Check if we need to retry or not.
        // TODO: We should support handover retry in the future.
        if (delay >= 0) {
            if (DBG) log("onDataSetupCompleteError: Try next APN. delay = " + delay);
            apnContext.setState(DctConstants.State.RETRYING);
            // Wait a bit before trying the next APN, so that
            // we're not tying up the RIL command channel

            startReconnect(delay, apnContext);
        } else {
            // If we are not going to retry any APN, set this APN context to failed state.
            // This would be the final state of a data connection.
            apnContext.setState(DctConstants.State.FAILED);
            mPhone.notifyDataConnection(apnContext.getApnType());
            apnContext.setDataConnection(null);
            if (DBG) log("onDataSetupCompleteError: Stop retrying APNs. delay=" + delay
                    + ", requestType=" + requestTypeToString(requestType));
        }
    }

    /*
     * Reset data reject params on data call success
     */
    private void handlePdpRejectCauseSuccess() {
        if (mDataRejectCount > 0) {
            if (DBG) log("handlePdpRejectCauseSuccess: reset reject count");
            resetDataRejectCounter();
        }
    }

        /*
     * Process data failure if RAT is WCDMA
     * And if the failure cause matches one of the following cause codes:
     * 1. USER_AUTHENTICATION
     * 2. SERVICE_OPTION_NOT_SUBSCRIBED
     * 3. MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED
     */
    private boolean handlePdpRejectCauseFailure(String reason) {
        boolean handleFailure = false;

        // Check if data rat is WCDMA
        if (isWCDMA(getDataRat())) {
            if (DBG) log("handlePdpRejectCauseFailure: reason=" + reason +
                    ", mDataRejectReason=" + mDataRejectReason);
            /*
             * If previously rejected code is not same as current data reject reason,
             * then reset the count and reset the reject reason
             */
            if (!reason.equalsIgnoreCase(mDataRejectReason)) {
                resetDataRejectCounter();
            }

            /*
             * If failure reason is USER_AUTHENTICATION or
             * SERVICE_OPTION_NOT_SUBSCRIBED or MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED,
             * increment counter and store reject cause
             */
            if (isMatchingPdpRejectCause(reason)) {
                mDataRejectCount++;
                mDataRejectReason = reason;
                if (DBG) log ("handlePdpRejectCauseFailure: DataRejectCount = " +
                        mDataRejectCount);
                handleFailure = true;
            }
        } else {
            if (DBG) log("isPdpRejectCauseFailureHandled: DataConnection not on wcdma");
            resetDataRejectCounter();
        }

        return handleFailure;
    }

    /*
     * Data reset event listener. Dc will get get onResetEvent
     * whenever any data reset event occurs
     */
    private VendorDataResetEventTracker.ResetEventListener mResetEventListener =
           new VendorDataResetEventTracker.ResetEventListener() {
        @Override
        public void onResetEvent(boolean retry) {
            if (DBG) log("onResetEvent: retry=" + retry);

            //Dismiss dialog
            if (mDataRejectDialog != null && mDataRejectDialog.isShowing()) {
                if (DBG) log("onResetEvent: Dismiss dialog");
                mDataRejectDialog.dismiss();
            }
            mVendorDataResetEventTracker.stopResetEventTracker();

            for (ApnContext apnContext : mApnContexts.values()) {
                if (mDataRejectCount > 0) {
                    if (DBG) log("onResetEvent: reset reject count=" + mDataRejectCount);
                    resetDataRejectCounter();
                    cancelReconnect(apnContext);
                    if (retry) {
                        if (DBG) log("onResetEvent: retry data call on apnContext=" + apnContext);
                        sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext));
                    }
                }
            }
        }
    };

    /**
     * This function will display the pdp reject message
     */
    private void displayPopup(String pdpRejectCause) {
        if (DBG) log("displayPopup : " + pdpRejectCause);
        String title = mPhone.getContext().getResources().
                getString(com.android.internal.R.string.config_pdp_reject_dialog_title);
        String message = null;
        if (pdpRejectCause.equalsIgnoreCase("USER_AUTHENTICATION")) {
            message = mPhone.getContext().getResources().
                    getString(com.android.internal.R.string.config_pdp_reject_user_authentication_failed);
        } else if (pdpRejectCause.equalsIgnoreCase("SERVICE_OPTION_NOT_SUBSCRIBED")) {
            message = mPhone.getContext().getResources().getString(
                    com.android.internal.R.string.config_pdp_reject_service_not_subscribed);
        } else if (pdpRejectCause.equalsIgnoreCase("MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED")) {
            message = mPhone.getContext().getResources().getString(
                    com.android.internal.R.string.config_pdp_reject_multi_conn_to_same_pdn_not_allowed);
        }
        if (mDataRejectDialog == null || !mDataRejectDialog.isShowing()) {
            AlertDialog.Builder builder = new AlertDialog.Builder(
                    mPhone.getContext());
            builder.setPositiveButton(android.R.string.ok, null);
            mDataRejectDialog = builder.create();
        }
        mDataRejectDialog.setMessage(message);
        mDataRejectDialog.setCanceledOnTouchOutside(false);
        mDataRejectDialog.setTitle(title);
        mDataRejectDialog.getWindow().setType(
                WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        mDataRejectDialog.show();
    }

    /*
     * returns true if data reject cause matches errors listed
     */
    private boolean isMatchingPdpRejectCause(String reason) {
        return reason.equalsIgnoreCase("USER_AUTHENTICATION") ||
               reason.equalsIgnoreCase("SERVICE_OPTION_NOT_SUBSCRIBED") ||
               reason.equalsIgnoreCase("MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED");
    }

    /**
     * returns true if radioTechnology is WCDMA rat, else false
     */
    private boolean isWCDMA(int radioTechnology) {
        return radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_UMTS
            || radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA
            || radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA
            || radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_HSPA
            || radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP;

    }

    /*
     * Reset data reject count and reason
     */
    private void resetDataRejectCounter() {
        mDataRejectCount = 0;
        mDataRejectReason = "NONE";
    }

    @Override
    protected void log(String s) {
        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
    }
}
