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

import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.compat.ImsService;
import android.telephony.ims.compat.feature.ImsFeature;
import android.telephony.ims.compat.feature.MMTelFeature;
import android.util.Log;
import android.util.SparseArray;

import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsMMTelFeature;
import com.android.ims.internal.IImsServiceController;

/**
 * Manages the Binding lifecycle of one ImsService as well as the relevant ImsFeatures that the
 * ImsService will support.
 *
 * Compatibility interface for interacting with older implementations of ImsService. The older
 * ImsService implementation is contained within the android.telephony.ims.compat.* namespace.
 * Newer implementations of ImsService should use the current APIs contained in
 * android.telephony.ims.*.
 */
public class ImsServiceControllerCompat extends ImsServiceController {

    private static final String TAG = "ImsSCCompat";

    private IImsServiceController mServiceController;

    private final SparseArray<MmTelFeatureCompatAdapter> mMmTelCompatAdapters = new SparseArray<>();
    private final SparseArray<ImsConfigCompatAdapter> mConfigCompatAdapters = new SparseArray<>();
    private final SparseArray<ImsRegistrationCompatAdapter> mRegCompatAdapters =
            new SparseArray<>();

    public ImsServiceControllerCompat(Context context, ComponentName componentName,
            ImsServiceController.ImsServiceControllerCallbacks callbacks) {
        super(context, componentName, callbacks);
    }

    @Override
    protected final String getServiceInterface() {
        // Return compatibility version of String.
        return ImsService.SERVICE_INTERFACE;
    }

    /**
     * Converts the new command to {@link MMTelFeature#turnOnIms()}.
     */
    @Override
    public final void enableIms(int slotId) {
        MmTelFeatureCompatAdapter adapter = mMmTelCompatAdapters.get(slotId);
        if (adapter == null) {
            Log.w(TAG, "enableIms: adapter null for slot :" + slotId);
            return;
        }
        try {
            adapter.enableIms();
        } catch (RemoteException e) {
            Log.w(TAG, "Couldn't enable IMS: " + e.getMessage());
        }
    }

    /**
     * Converts the new command to {@link MMTelFeature#turnOffIms()}.
     */
    @Override
    public final void disableIms(int slotId) {
        MmTelFeatureCompatAdapter adapter = mMmTelCompatAdapters.get(slotId);
        if (adapter == null) {
            Log.w(TAG, "enableIms: adapter null for slot :" + slotId);
            return;
        }
        try {
            adapter.disableIms();
        } catch (RemoteException e) {
            Log.w(TAG, "Couldn't enable IMS: " + e.getMessage());
        }
    }

    /**
     * @return the IImsRegistration that corresponds to the slot id specified.
     */
    @Override
    public final IImsRegistration getRegistration(int slotId) {
        ImsRegistrationCompatAdapter adapter = mRegCompatAdapters.get(slotId);
        if (adapter == null) {
            Log.w(TAG, "getRegistration: Registration does not exist for slot " + slotId);
            return null;
        }
        return adapter.getBinder();
    }

    /**
     * @return the IImsConfig that corresponds to the slot id specified.
     */
    @Override
    public final IImsConfig getConfig(int slotId) {
        ImsConfigCompatAdapter adapter = mConfigCompatAdapters.get(slotId);
        if (adapter == null) {
            Log.w(TAG, "getConfig: Config does not exist for slot " + slotId);
            return null;
        }
        return adapter.getIImsConfig();
    }

    @Override
    protected final void notifyImsServiceReady() {
        Log.d(TAG, "notifyImsServiceReady");
        // don't do anything for compat impl.
    }

    @Override
    protected final IInterface createImsFeature(int slotId, int featureType,
            IImsFeatureStatusCallback c)
            throws RemoteException {
        switch (featureType) {
            case ImsFeature.MMTEL: {
                return createMMTelCompat(slotId, c);
            }
            case ImsFeature.RCS: {
                return createRcsFeature(slotId, c);
            }
            default:
                return null;
        }
    }

    @Override
    protected final void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        if (featureType == ImsFeature.MMTEL) {
            mMmTelCompatAdapters.remove(slotId);
            mRegCompatAdapters.remove(slotId);
            mConfigCompatAdapters.remove(slotId);
        }
        if (mServiceController != null) {
            mServiceController.removeImsFeature(slotId, featureType, c);
        }
    }

    @Override
    protected void setServiceController(IBinder serviceController) {
        mServiceController = IImsServiceController.Stub.asInterface(serviceController);
    }

    @Override
    protected boolean isServiceControllerAvailable() {
        return mServiceController != null;
    }

    private MmTelInterfaceAdapter getInterface(int slotId, IImsFeatureStatusCallback c)
            throws RemoteException {
        IImsMMTelFeature feature = mServiceController.createMMTelFeature(slotId, c);
        if (feature == null) {
            Log.w(TAG, "createMMTelCompat: createMMTelFeature returned null.");
            return null;
        }
        return new MmTelInterfaceAdapter(slotId, feature.asBinder());
    }

    private IImsMmTelFeature createMMTelCompat(int slotId, IImsFeatureStatusCallback c)
            throws RemoteException {
        MmTelInterfaceAdapter interfaceAdapter = getInterface(slotId, c);
        MmTelFeatureCompatAdapter mmTelAdapter = new MmTelFeatureCompatAdapter(mContext, slotId,
                interfaceAdapter);
        mMmTelCompatAdapters.put(slotId, mmTelAdapter);
        ImsRegistrationCompatAdapter regAdapter = new ImsRegistrationCompatAdapter();
        mmTelAdapter.addRegistrationAdapter(regAdapter);
        mRegCompatAdapters.put(slotId, regAdapter);
        mConfigCompatAdapters.put(slotId, new ImsConfigCompatAdapter(
                mmTelAdapter.getOldConfigInterface()));
        return mmTelAdapter.getBinder();
    }

    private IImsRcsFeature createRcsFeature(int slotId, IImsFeatureStatusCallback c) {
        // Return non-null if there is a custom RCS implementation that needs a compatability layer.
        return null;
    }
}
