/*
 * 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.internal.telephony;

import android.content.Context;
import android.os.Binder;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SmsManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.telephony.ims.stub.ImsSmsImplBase.SendStatusResult;

import com.android.ims.FeatureConnector;
import com.android.ims.ImsException;
import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.GsmAlphabet.TextEncodingDetails;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.telephony.util.SMSDispatcherUtil;
import com.android.telephony.Rlog;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Responsible for communications with {@link com.android.ims.ImsManager} to send/receive messages
 * over IMS.
 * @hide
 */
public class ImsSmsDispatcher extends SMSDispatcher {

    private static final String TAG = "ImsSmsDispatcher";
    private static final int CONNECT_DELAY_MS = 5000; // 5 seconds;

    /**
     * Creates FeatureConnector instances for ImsManager, used during testing to inject mock
     * connector instances.
     */
    @VisibleForTesting
    public interface FeatureConnectorFactory {
        /**
         * Create a new FeatureConnector for ImsManager.
         */
        FeatureConnector<ImsManager> create(Context context, int phoneId, String logPrefix,
                FeatureConnector.Listener<ImsManager> listener, Executor executor);
    }

    @VisibleForTesting
    public Map<Integer, SmsTracker> mTrackers = new ConcurrentHashMap<>();
    @VisibleForTesting
    public AtomicInteger mNextToken = new AtomicInteger();
    private final Object mLock = new Object();
    private volatile boolean mIsSmsCapable;
    private volatile boolean mIsImsServiceUp;
    private volatile boolean mIsRegistered;
    private final FeatureConnector<ImsManager> mImsManagerConnector;
    /** Telephony metrics instance for logging metrics event */
    private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance();
    private ImsManager mImsManager;
    private FeatureConnectorFactory mConnectorFactory;

    private Runnable mConnectRunnable = new Runnable() {
        @Override
        public void run() {
            mImsManagerConnector.connect();
        }
    };

    /**
     * Listen to the IMS service state change
     *
     */
    private RegistrationManager.RegistrationCallback mRegistrationCallback =
            new RegistrationManager.RegistrationCallback() {
                @Override
                public void onRegistered(
                        @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) {
                    logd("onImsConnected imsRadioTech=" + imsRadioTech);
                    synchronized (mLock) {
                        mIsRegistered = true;
                    }
                }

                @Override
                public void onRegistering(
                        @ImsRegistrationImplBase.ImsRegistrationTech int imsRadioTech) {
                    logd("onImsProgressing imsRadioTech=" + imsRadioTech);
                    synchronized (mLock) {
                        mIsRegistered = false;
                    }
                }

                @Override
                public void onUnregistered(ImsReasonInfo info) {
                    logd("onImsDisconnected imsReasonInfo=" + info);
                    synchronized (mLock) {
                        mIsRegistered = false;
                    }
                }
            };

    private android.telephony.ims.ImsMmTelManager.CapabilityCallback mCapabilityCallback =
            new android.telephony.ims.ImsMmTelManager.CapabilityCallback() {
                @Override
                public void onCapabilitiesStatusChanged(
                        MmTelFeature.MmTelCapabilities capabilities) {
                    synchronized (mLock) {
                        mIsSmsCapable = capabilities.isCapable(
                                MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS);
                    }
                }
    };

    private final IImsSmsListener mImsSmsListener = new IImsSmsListener.Stub() {
        @Override
        public void onSendSmsResult(int token, int messageRef, @SendStatusResult int status,
                @SmsManager.Result int reason, int networkReasonCode) {
            final long identity = Binder.clearCallingIdentity();
            try {
                logd("onSendSmsResult token=" + token + " messageRef=" + messageRef
                        + " status=" + status + " reason=" + reason + " networkReasonCode="
                        + networkReasonCode);
                // TODO integrate networkReasonCode into IMS SMS metrics.
                SmsTracker tracker = mTrackers.get(token);
                mMetrics.writeOnImsServiceSmsSolicitedResponse(mPhone.getPhoneId(), status, reason,
                        (tracker != null ? tracker.mMessageId : 0L));
                if (tracker == null) {
                    throw new IllegalArgumentException("Invalid token.");
                }
                tracker.mMessageRef = messageRef;
                switch(status) {
                    case ImsSmsImplBase.SEND_STATUS_OK:
                        if (tracker.mDeliveryIntent != null) {
                            // Expecting a status report. Put this tracker to the map.
                            mSmsDispatchersController.putDeliveryPendingTracker(tracker);
                        }
                        tracker.onSent(mContext);
                        mTrackers.remove(token);
                        mPhone.notifySmsSent(tracker.mDestAddress);
                        break;
                    case ImsSmsImplBase.SEND_STATUS_ERROR:
                        tracker.onFailed(mContext, reason, networkReasonCode);
                        mTrackers.remove(token);
                        break;
                    case ImsSmsImplBase.SEND_STATUS_ERROR_RETRY:
                        tracker.mRetryCount += 1;
                        sendSms(tracker);
                        break;
                    case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
                        tracker.mRetryCount += 1;
                        mTrackers.remove(token);
                        fallbackToPstn(tracker);
                        break;
                    default:
                }
                mPhone.getSmsStats().onOutgoingSms(
                        true /* isOverIms */,
                        SmsConstants.FORMAT_3GPP2.equals(getFormat()),
                        status == ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK,
                        reason,
                        tracker.mMessageId,
                        tracker.isFromDefaultSmsApplication(mContext));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        @Override
        public void onSmsStatusReportReceived(int token, String format, byte[] pdu)
                throws RemoteException {
            final long identity = Binder.clearCallingIdentity();
            try {
                logd("Status report received.");
                android.telephony.SmsMessage message =
                        android.telephony.SmsMessage.createFromPdu(pdu, format);
                if (message == null || message.mWrappedSmsMessage == null) {
                    throw new RemoteException(
                            "Status report received with a PDU that could not be parsed.");
                }
                mSmsDispatchersController.handleSmsStatusReport(format, pdu);
                try {
                    getImsManager().acknowledgeSmsReport(
                            token,
                            message.mWrappedSmsMessage.mMessageRef,
                            ImsSmsImplBase.STATUS_REPORT_STATUS_OK);
                } catch (ImsException e) {
                    loge("Failed to acknowledgeSmsReport(). Error: " + e.getMessage());
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

        @Override
        public void onSmsReceived(int token, String format, byte[] pdu) {
            final long identity = Binder.clearCallingIdentity();
            try {
                logd("SMS received.");
                android.telephony.SmsMessage message =
                        android.telephony.SmsMessage.createFromPdu(pdu, format);
                mSmsDispatchersController.injectSmsPdu(message, format, result -> {
                    logd("SMS handled result: " + result);
                    int mappedResult;
                    switch (result) {
                        case Intents.RESULT_SMS_HANDLED:
                            mappedResult = ImsSmsImplBase.DELIVER_STATUS_OK;
                            break;
                        case Intents.RESULT_SMS_OUT_OF_MEMORY:
                            mappedResult = ImsSmsImplBase.DELIVER_STATUS_ERROR_NO_MEMORY;
                            break;
                        case Intents.RESULT_SMS_UNSUPPORTED:
                            mappedResult =
                                    ImsSmsImplBase.DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED;
                            break;
                        default:
                            mappedResult = ImsSmsImplBase.DELIVER_STATUS_ERROR_GENERIC;
                            break;
                    }
                    try {
                        if (message != null && message.mWrappedSmsMessage != null) {
                            getImsManager().acknowledgeSms(token,
                                    message.mWrappedSmsMessage.mMessageRef, mappedResult);
                        } else {
                            logw("SMS Received with a PDU that could not be parsed.");
                            getImsManager().acknowledgeSms(token, 0, mappedResult);
                        }
                    } catch (ImsException e) {
                        loge("Failed to acknowledgeSms(). Error: " + e.getMessage());
                    }
                }, true /* ignoreClass */, true /* isOverIms */);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    };

    public ImsSmsDispatcher(Phone phone, SmsDispatchersController smsDispatchersController,
            FeatureConnectorFactory factory) {
        super(phone, smsDispatchersController);
        mConnectorFactory = factory;

        mImsManagerConnector = mConnectorFactory.create(mContext, mPhone.getPhoneId(), TAG,
                new FeatureConnector.Listener<ImsManager>() {
                    public void connectionReady(ImsManager manager) throws ImsException {
                        logd("ImsManager: connection ready.");
                        synchronized (mLock) {
                            mImsManager = manager;
                            setListeners();
                            mIsImsServiceUp = true;
                        }
                    }

                    @Override
                    public void connectionUnavailable(int reason) {
                        logd("ImsManager: connection unavailable, reason=" + reason);
                        if (reason == FeatureConnector.UNAVAILABLE_REASON_SERVER_UNAVAILABLE) {
                            loge("connectionUnavailable: unexpected, received server error");
                            removeCallbacks(mConnectRunnable);
                            postDelayed(mConnectRunnable, CONNECT_DELAY_MS);
                        }
                        synchronized (mLock) {
                            mImsManager = null;
                            mIsImsServiceUp = false;
                        }
                    }
                }, this::post);
        post(mConnectRunnable);
    }

    private void setListeners() throws ImsException {
        getImsManager().addRegistrationCallback(mRegistrationCallback, this::post);
        getImsManager().addCapabilitiesCallback(mCapabilityCallback, this::post);
        getImsManager().setSmsListener(getSmsListener());
        getImsManager().onSmsReady();
    }

    private boolean isLteService() {
        return ((mPhone.getServiceState().getRilDataRadioTechnology() ==
            ServiceState.RIL_RADIO_TECHNOLOGY_LTE) && (mPhone.getServiceState().
                getDataRegistrationState() == ServiceState.STATE_IN_SERVICE));
    }

    private boolean isLimitedLteService() {
        return ((mPhone.getServiceState().getRilVoiceRadioTechnology() ==
            ServiceState.RIL_RADIO_TECHNOLOGY_LTE) && mPhone.getServiceState().isEmergencyOnly());
    }

    private boolean isEmergencySmsPossible() {
        return isLteService() || isLimitedLteService();
    }

    public boolean isEmergencySmsSupport(String destAddr) {
        PersistableBundle b;
        boolean eSmsCarrierSupport = false;
        if (!mTelephonyManager.isEmergencyNumber(destAddr)) {
            logi(Rlog.pii(TAG, destAddr) + " is not emergency number");
            return false;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            CarrierConfigManager configManager = (CarrierConfigManager) mContext
                    .getSystemService(Context.CARRIER_CONFIG_SERVICE);
            if (configManager == null) {
                loge("configManager is null");
                return false;
            }
            b = configManager.getConfigForSubId(getSubId());
            if (b == null) {
                loge("PersistableBundle is null");
                return false;
            }
            eSmsCarrierSupport = b.getBoolean(
                    CarrierConfigManager.KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL);
            boolean lteOrLimitedLte = isEmergencySmsPossible();
            logi("isEmergencySmsSupport emergencySmsCarrierSupport: "
                    + eSmsCarrierSupport + " destAddr: " + Rlog.pii(TAG, destAddr)
                    + " mIsImsServiceUp: " + mIsImsServiceUp + " lteOrLimitedLte: "
                    + lteOrLimitedLte);

            return eSmsCarrierSupport && mIsImsServiceUp && lteOrLimitedLte;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public boolean isAvailable() {
        synchronized (mLock) {
            logd("isAvailable: up=" + mIsImsServiceUp + ", reg= " + mIsRegistered
                    + ", cap= " + mIsSmsCapable);
            return mIsImsServiceUp && mIsRegistered && mIsSmsCapable;
        }
    }

    @Override
    protected String getFormat() {
        // This is called in the constructor before ImsSmsDispatcher has a chance to initialize
        // mLock. ImsManager will not be up anyway at this point, so report UNKNOWN.
        if (mLock == null) return SmsConstants.FORMAT_UNKNOWN;
        try {
            return getImsManager().getSmsFormat();
        } catch (ImsException e) {
            loge("Failed to get sms format. Error: " + e.getMessage());
            return SmsConstants.FORMAT_UNKNOWN;
        }
    }

    @Override
    protected boolean shouldBlockSmsForEcbm() {
        // We should not block outgoing SMS during ECM on IMS. It only applies to outgoing CDMA
        // SMS.
        return false;
    }

    @Override
    protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
            String message, boolean statusReportRequested, SmsHeader smsHeader, int priority,
            int validityPeriod) {
        return SMSDispatcherUtil.getSubmitPdu(isCdmaMo(), scAddr, destAddr, message,
                statusReportRequested, smsHeader, priority, validityPeriod);
    }

    @Override
    protected SmsMessageBase.SubmitPduBase getSubmitPdu(String scAddr, String destAddr,
            int destPort, byte[] message, boolean statusReportRequested) {
        return SMSDispatcherUtil.getSubmitPdu(isCdmaMo(), scAddr, destAddr, destPort, message,
                statusReportRequested);
    }

    @Override
    protected TextEncodingDetails calculateLength(CharSequence messageBody, boolean use7bitOnly) {
        return SMSDispatcherUtil.calculateLength(isCdmaMo(), messageBody, use7bitOnly);
    }

    @Override
    public void sendSms(SmsTracker tracker) {
        logd("sendSms: "
                + " mRetryCount=" + tracker.mRetryCount
                + " mMessageRef=" + tracker.mMessageRef
                + " SS=" + mPhone.getServiceState().getState());

        // Flag that this Tracker is using the ImsService implementation of SMS over IMS for sending
        // this message. Any fallbacks will happen over CS only.
        tracker.mUsesImsServiceForIms = true;

        HashMap<String, Object> map = tracker.getData();

        byte[] pdu = (byte[]) map.get(MAP_KEY_PDU);
        byte smsc[] = (byte[]) map.get(MAP_KEY_SMSC);
        boolean isRetry = tracker.mRetryCount > 0;
        String format = getFormat();

        if (SmsConstants.FORMAT_3GPP.equals(format) && tracker.mRetryCount > 0) {
            // per TS 23.040 Section 9.2.3.6:  If TP-MTI SMS-SUBMIT (0x01) type
            //   TP-RD (bit 2) is 1 for retry
            //   and TP-MR is set to previously failed sms TP-MR
            if (((0x01 & pdu[0]) == 0x01)) {
                pdu[0] |= 0x04; // TP-RD
                pdu[1] = (byte) tracker.mMessageRef; // TP-MR
            }
        }

        int token = mNextToken.incrementAndGet();
        mTrackers.put(token, tracker);
        try {
            getImsManager().sendSms(
                    token,
                    tracker.mMessageRef,
                    format,
                    smsc != null ? IccUtils.bytesToHexString(smsc) : null,
                    isRetry,
                    pdu);
            mMetrics.writeImsServiceSendSms(mPhone.getPhoneId(), format,
                    ImsSmsImplBase.SEND_STATUS_OK, tracker.mMessageId);
        } catch (ImsException e) {
            loge("sendSms failed. Falling back to PSTN. Error: " + e.getMessage());
            mTrackers.remove(token);
            fallbackToPstn(tracker);
            mMetrics.writeImsServiceSendSms(mPhone.getPhoneId(), format,
                    ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK, tracker.mMessageId);
            mPhone.getSmsStats().onOutgoingSms(
                    true /* isOverIms */,
                    SmsConstants.FORMAT_3GPP2.equals(format),
                    true /* fallbackToCs */,
                    SmsManager.RESULT_SYSTEM_ERROR,
                    tracker.mMessageId,
                    tracker.isFromDefaultSmsApplication(mContext));
        }
    }

    private ImsManager getImsManager() throws ImsException {
        synchronized (mLock) {
            if (mImsManager == null) {
                throw new ImsException("ImsManager not up",
                        ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
            }
            return mImsManager;
        }
    }

    @VisibleForTesting
    public void fallbackToPstn(SmsTracker tracker) {
        mSmsDispatchersController.sendRetrySms(tracker);
    }

    @Override
    protected boolean isCdmaMo() {
        return mSmsDispatchersController.isCdmaFormat(getFormat());
    }

    @VisibleForTesting
    public IImsSmsListener getSmsListener() {
        return mImsSmsListener;
    }

    private void logd(String s) {
        Rlog.d(TAG + " [" + getPhoneId(mPhone) + "]", s);
    }

    private void logi(String s) {
        Rlog.i(TAG + " [" + getPhoneId(mPhone) + "]", s);
    }

    private void logw(String s) {
        Rlog.w(TAG + " [" + getPhoneId(mPhone) + "]", s);
    }

    private void loge(String s) {
        Rlog.e(TAG + " [" + getPhoneId(mPhone) + "]", s);
    }

    private static String getPhoneId(Phone phone) {
        return (phone != null) ? Integer.toString(phone.getPhoneId()) : "?";
    }
}
