/*
 * Copyright (C) 2006 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;

import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.SystemProperties;
import android.telephony.CarrierConfigManager;
import android.text.TextUtils;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;


/**
 * {@hide}
 */
public abstract class CallTracker extends Handler {

    private static final boolean DBG_POLL = false;

    //***** Constants

    static final int POLL_DELAY_MSEC = 250;

    @UnsupportedAppUsage
    protected int mPendingOperations;
    @UnsupportedAppUsage
    protected boolean mNeedsPoll;
    protected Message mLastRelevantPoll;
    protected ArrayList<Connection> mHandoverConnections = new ArrayList<Connection>();

    @UnsupportedAppUsage
    public CommandsInterface mCi;

    @UnsupportedAppUsage
    protected boolean mNumberConverted = false;
    private final int VALID_COMPARE_LENGTH   = 3;

    //***** Events

    protected static final int EVENT_POLL_CALLS_RESULT             = 1;
    protected static final int EVENT_CALL_STATE_CHANGE             = 2;
    protected static final int EVENT_REPOLL_AFTER_DELAY            = 3;
    protected static final int EVENT_OPERATION_COMPLETE            = 4;
    protected static final int EVENT_GET_LAST_CALL_FAIL_CAUSE      = 5;

    protected static final int EVENT_SWITCH_RESULT                 = 8;
    protected static final int EVENT_RADIO_AVAILABLE               = 9;
    protected static final int EVENT_RADIO_NOT_AVAILABLE           = 10;
    protected static final int EVENT_CONFERENCE_RESULT             = 11;
    protected static final int EVENT_SEPARATE_RESULT               = 12;
    protected static final int EVENT_ECT_RESULT                    = 13;
    protected static final int EVENT_EXIT_ECM_RESPONSE_CDMA        = 14;
    protected static final int EVENT_CALL_WAITING_INFO_CDMA        = 15;
    protected static final int EVENT_THREE_WAY_DIAL_L2_RESULT_CDMA = 16;
    protected static final int EVENT_THREE_WAY_DIAL_BLANK_FLASH    = 20;

    @UnsupportedAppUsage
    public CallTracker() {
    }

    protected void pollCallsWhenSafe() {
        mNeedsPoll = true;

        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            mCi.getCurrentCalls(mLastRelevantPoll);
        }
    }

    protected void
    pollCallsAfterDelay() {
        Message msg = obtainMessage();

        msg.what = EVENT_REPOLL_AFTER_DELAY;
        sendMessageDelayed(msg, POLL_DELAY_MSEC);
    }

    protected boolean
    isCommandExceptionRadioNotAvailable(Throwable e) {
        return e != null && e instanceof CommandException
                && ((CommandException)e).getCommandError()
                        == CommandException.Error.RADIO_NOT_AVAILABLE;
    }

    protected abstract void handlePollCalls(AsyncResult ar);

    protected abstract Phone getPhone();

    protected Connection getHoConnection(DriverCall dc) {
        for (Connection hoConn : mHandoverConnections) {
            log("getHoConnection - compare number: hoConn= " + hoConn.toString());
            if (hoConn.getAddress() != null && hoConn.getAddress().contains(dc.number)) {
                log("getHoConnection: Handover connection match found = " + hoConn.toString());
                return hoConn;
            }
        }
        for (Connection hoConn : mHandoverConnections) {
            log("getHoConnection: compare state hoConn= " + hoConn.toString());
            if (hoConn.getStateBeforeHandover() == Call.stateFromDCState(dc.state)) {
                log("getHoConnection: Handover connection match found = " + hoConn.toString());
                return hoConn;
            }
        }
        return null;
    }

    protected void notifySrvccState(Call.SrvccState state, ArrayList<Connection> c) {
        if (state == Call.SrvccState.STARTED && c != null) {
            // SRVCC started. Prepare handover connections list
            mHandoverConnections.addAll(c);
        } else if (state != Call.SrvccState.COMPLETED) {
            // SRVCC FAILED/CANCELED. Clear the handover connections list
            // Individual connections will be removed from the list in handlePollCalls()
            mHandoverConnections.clear();
        }
        log("notifySrvccState: mHandoverConnections= " + mHandoverConnections.toString());
    }

    protected void handleRadioAvailable() {
        pollCallsWhenSafe();
    }

    /**
     * Obtain a complete message that indicates that this operation
     * does not require polling of getCurrentCalls(). However, if other
     * operations that do need getCurrentCalls() are pending or are
     * scheduled while this operation is pending, the invocation
     * of getCurrentCalls() will be postponed until this
     * operation is also complete.
     */
    protected Message
    obtainNoPollCompleteMessage(int what) {
        mPendingOperations++;
        mLastRelevantPoll = null;
        return obtainMessage(what);
    }

    /**
     * @return true if we're idle or there's a call to getCurrentCalls() pending
     * but nothing else
     */
    private boolean
    checkNoOperationsPending() {
        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
                mPendingOperations);
        return mPendingOperations == 0;
    }

    /**
     * Routine called from dial to check if the number is a test Emergency number
     * and if so remap the number. This allows a short emergency number to be remapped
     * to a regular number for testing how the frameworks handles emergency numbers
     * without actually calling an emergency number.
     *
     * This is not a full test and is not a substitute for testing real emergency
     * numbers but can be useful.
     *
     * To use this feature set a system property ril.test.emergencynumber to a pair of
     * numbers separated by a colon. If the first number matches the number parameter
     * this routine returns the second number. Example:
     *
     * ril.test.emergencynumber=112:1-123-123-45678
     *
     * To test Dial 112 take call then hang up on MO device to enter ECM
     * see RIL#processSolicited RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND
     *
     * @param dialString to test if it should be remapped
     * @return the same number or the remapped number.
     */
    protected String checkForTestEmergencyNumber(String dialString) {
        String testEn = SystemProperties.get("ril.test.emergencynumber");
        if (DBG_POLL) {
            log("checkForTestEmergencyNumber: dialString=" + dialString +
                " testEn=" + testEn);
        }
        if (!TextUtils.isEmpty(testEn)) {
            String values[] = testEn.split(":");
            log("checkForTestEmergencyNumber: values.length=" + values.length);
            if (values.length == 2) {
                if (values[0].equals(
                        android.telephony.PhoneNumberUtils.stripSeparators(dialString))) {
                    // mCi will be null for ImsPhoneCallTracker.
                    if (mCi != null) {
                        mCi.testingEmergencyCall();
                    }
                    log("checkForTestEmergencyNumber: remap " +
                            dialString + " to " + values[1]);
                    dialString = values[1];
                }
            }
        }
        return dialString;
    }

    protected String convertNumberIfNecessary(Phone phone, String dialNumber) {
        if (dialNumber == null) {
            return dialNumber;
        }
        String[] convertMaps = null;
        CarrierConfigManager configManager = (CarrierConfigManager)
                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle bundle = configManager.getConfigForSubId(phone.getSubId());
        if (bundle != null) {
            convertMaps =
                    bundle.getStringArray(CarrierConfigManager.KEY_DIAL_STRING_REPLACE_STRING_ARRAY);
        }
        if (convertMaps == null) {
            // By default no replacement is necessary
            log("convertNumberIfNecessary convertMaps is null");
            return dialNumber;
        }

        log("convertNumberIfNecessary Roaming"
            + " convertMaps.length " + convertMaps.length
            + " dialNumber.length() " + dialNumber.length());

        if (convertMaps.length < 1 || dialNumber.length() < VALID_COMPARE_LENGTH) {
            return dialNumber;
        }

        String[] entry;
        String outNumber = "";
        for(String convertMap : convertMaps) {
            log("convertNumberIfNecessary: " + convertMap);
            // entry format is  "dialStringToReplace:dialStringReplacement"
            entry = convertMap.split(":");
            if (entry != null && entry.length > 1) {
                String dsToReplace = entry[0];
                String dsReplacement = entry[1];
                if (!TextUtils.isEmpty(dsToReplace) && dialNumber.equals(dsToReplace)) {
                    // Needs to be converted
                    if (!TextUtils.isEmpty(dsReplacement) && dsReplacement.endsWith("MDN")) {
                        String mdn = phone.getLine1Number();
                        if (!TextUtils.isEmpty(mdn)) {
                            if (mdn.startsWith("+")) {
                                outNumber = mdn;
                            } else {
                                outNumber = dsReplacement.substring(0, dsReplacement.length() -3)
                                        + mdn;
                            }
                        }
                    } else {
                        outNumber = dsReplacement;
                    }
                    break;
                }
            }
        }

        if (!TextUtils.isEmpty(outNumber)) {
            log("convertNumberIfNecessary: convert service number");
            mNumberConverted = true;
            return outNumber;
        }

        return dialNumber;

    }

    private boolean compareGid1(Phone phone, String serviceGid1) {
        String gid1 = phone.getGroupIdLevel1();
        int gid_length = serviceGid1.length();
        boolean ret = true;

        if (serviceGid1 == null || serviceGid1.equals("")) {
            log("compareGid1 serviceGid is empty, return " + ret);
            return ret;
        }
        // Check if gid1 match service GID1
        if (!((gid1 != null) && (gid1.length() >= gid_length) &&
                gid1.substring(0, gid_length).equalsIgnoreCase(serviceGid1))) {
            log(" gid1 " + gid1 + " serviceGid1 " + serviceGid1);
            ret = false;
        }
        log("compareGid1 is " + (ret?"Same":"Different"));
        return ret;
    }

    /**
     * Get the ringing connections which during SRVCC handover.
     */
    public Connection getRingingHandoverConnection() {
        for (Connection hoConn : mHandoverConnections) {
            if (hoConn.getCall().isRinging()) {
                return hoConn;
            }
        }
        return null;
    }

    //***** Overridden from Handler
    @Override
    public abstract void handleMessage (Message msg);
    public abstract void registerForVoiceCallStarted(Handler h, int what, Object obj);
    public abstract void unregisterForVoiceCallStarted(Handler h);
    @UnsupportedAppUsage
    public abstract void registerForVoiceCallEnded(Handler h, int what, Object obj);
    public abstract void unregisterForVoiceCallEnded(Handler h);
    @UnsupportedAppUsage
    public abstract PhoneConstants.State getState();
    @UnsupportedAppUsage
    protected abstract void log(String msg);

    /**
     * Called when the call tracker should attempt to reconcile its calls against its underlying
     * phone implementation and cleanup any stale calls.
     */
    public void cleanupCalls() {
        // no base implementation
    }

    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("CallTracker:");
        pw.println(" mPendingOperations=" + mPendingOperations);
        pw.println(" mNeedsPoll=" + mNeedsPoll);
        pw.println(" mLastRelevantPoll=" + mLastRelevantPoll);
    }
}
