/*
 * Copyright (c) 2021 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.ims.rcs.uce.request;

import static android.telephony.ims.stub.RcsCapabilityExchangeImplBase.COMMAND_CODE_GENERIC_FAILURE;

import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.aidl.IRcsUceControllerCallback;

import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
import com.android.internal.annotations.VisibleForTesting;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

/**
 * Responsible for the communication and interaction between OptionsRequests and triggering
 * the callback to notify the result of the capabilities request.
 */
public class OptionsRequestCoordinator extends UceRequestCoordinator {
    /**
     * The builder of the OptionsRequestCoordinator.
     */
    public static final class Builder {
        private OptionsRequestCoordinator mRequestCoordinator;

        public Builder(int subId, Collection<UceRequest> requests,
                RequestManagerCallback callback) {
            mRequestCoordinator = new OptionsRequestCoordinator(subId, requests, callback);
        }

        public Builder setCapabilitiesCallback(IRcsUceControllerCallback callback) {
            mRequestCoordinator.setCapabilitiesCallback(callback);
            return this;
        }

        public OptionsRequestCoordinator build() {
            return mRequestCoordinator;
        }
    }

    /**
     * Different request updated events will create different {@link RequestResult}. Define the
     * interface to get the {@link RequestResult} instance according to the given task ID and
     * {@link CapabilityRequestResponse}.
     */
    @FunctionalInterface
    private interface RequestResultCreator {
        RequestResult createRequestResult(long taskId, CapabilityRequestResponse response);
    }

    // The RequestResult creator of the request error.
    private static final RequestResultCreator sRequestErrorCreator = (taskId, response) -> {
        int errorCode = response.getRequestInternalError().orElse(DEFAULT_ERROR_CODE);
        long retryAfter = response.getRetryAfterMillis();
        return RequestResult.createFailedResult(taskId, errorCode, retryAfter);
    };

    // The RequestResult creator of the request command error.
    private static final RequestResultCreator sCommandErrorCreator = (taskId, response) -> {
        int cmdError = response.getCommandError().orElse(COMMAND_CODE_GENERIC_FAILURE);
        int errorCode = CapabilityRequestResponse.getCapabilityErrorFromCommandError(cmdError);
        long retryAfter = response.getRetryAfterMillis();
        return RequestResult.createFailedResult(taskId, errorCode, retryAfter);
    };

    // The RequestResult creator of the network response.
    private static final RequestResultCreator sNetworkRespCreator = (taskId, response) -> {
        if (response.isNetworkResponseOK()) {
            return RequestResult.createSuccessResult(taskId);
        } else {
            int errorCode = CapabilityRequestResponse.getCapabilityErrorFromSipCode(response);
            long retryAfter = response.getRetryAfterMillis();
            return RequestResult.createFailedResult(taskId, errorCode, retryAfter);
        }
    };

    // The RequestResult creator for does not need to request from the network.
    private static final RequestResultCreator sNotNeedRequestFromNetworkCreator =
            (taskId, response) -> RequestResult.createSuccessResult(taskId);

    // The RequestResult creator of the request timeout.
    private static final RequestResultCreator sRequestTimeoutCreator =
            (taskId, response) -> RequestResult.createFailedResult(taskId,
                    RcsUceAdapter.ERROR_REQUEST_TIMEOUT, 0L);

    // The callback to notify the result of the capabilities request.
    private IRcsUceControllerCallback mCapabilitiesCallback;

    private OptionsRequestCoordinator(int subId, Collection<UceRequest> requests,
            RequestManagerCallback requestMgrCallback) {
        super(subId, requests, requestMgrCallback);
        logd("OptionsRequestCoordinator: created");
    }

    private void setCapabilitiesCallback(IRcsUceControllerCallback callback) {
        mCapabilitiesCallback = callback;
    }

    @Override
    public void onFinish() {
        logd("OptionsRequestCoordinator: onFinish");
        mCapabilitiesCallback = null;
        super.onFinish();
    }

    @Override
    public void onRequestUpdated(long taskId, @UceRequestUpdate int event) {
        if (mIsFinished) return;
        OptionsRequest request = (OptionsRequest) getUceRequest(taskId);
        if (request == null) {
            logw("onRequestUpdated: Cannot find OptionsRequest taskId=" + taskId);
            return;
        }

        logd("onRequestUpdated(OptionsRequest): taskId=" + taskId + ", event=" +
                REQUEST_EVENT_DESC.get(event));

        switch (event) {
            case REQUEST_UPDATE_ERROR:
                handleRequestError(request);
                break;
            case REQUEST_UPDATE_COMMAND_ERROR:
                handleCommandError(request);
                break;
            case REQUEST_UPDATE_NETWORK_RESPONSE:
                handleNetworkResponse(request);
                break;
            case REQUEST_UPDATE_CACHED_CAPABILITY_UPDATE:
                handleCachedCapabilityUpdated(request);
                break;
            case REQUEST_UPDATE_NO_NEED_REQUEST_FROM_NETWORK:
                handleNoNeedRequestFromNetwork(request);
                break;
            case REQUEST_UPDATE_TIMEOUT:
                handleRequestTimeout(request);
                break;
            default:
                logw("onRequestUpdated(OptionsRequest): invalid event " + event);
                break;
        }

        // End this instance if all the UceRequests in the coordinator are finished.
        checkAndFinishRequestCoordinator();
    }

    /**
     * Finish the OptionsRequest because it has encountered error.
     */
    private void handleRequestError(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        logd("handleRequestError: " + request.toString());

        // Finish this request.
        request.onFinish();

        // Remove this request from the activated collection and notify RequestManager.
        Long taskId = request.getTaskId();
        RequestResult requestResult = sRequestErrorCreator.createRequestResult(taskId, response);
        moveRequestToFinishedCollection(taskId, requestResult);
    }

    /**
     * This method is called when the given OptionsRequest received the onCommandError callback
     * from the ImsService.
     */
    private void handleCommandError(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        logd("handleCommandError: " + request.toString());

        // Finish this request.
        request.onFinish();

        // Remove this request from the activated collection and notify RequestManager.
        Long taskId = request.getTaskId();
        RequestResult requestResult = sCommandErrorCreator.createRequestResult(taskId, response);
        moveRequestToFinishedCollection(taskId, requestResult);
    }

    /**
     * This method is called when the given OptionsRequest received the onNetworkResponse
     * callback from the ImsService.
     */
    private void handleNetworkResponse(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        logd("handleNetworkResponse: " + response.toString());

        List<RcsContactUceCapability> updatedCapList = response.getUpdatedContactCapability();
        if (!updatedCapList.isEmpty()) {
            // Save the capabilities and trigger the capabilities callback
            mRequestManagerCallback.saveCapabilities(updatedCapList);
            triggerCapabilitiesReceivedCallback(updatedCapList);
            response.removeUpdatedCapabilities(updatedCapList);
        }

        // Finish this request.
        request.onFinish();

        // Remove this request from the activated collection and notify RequestManager.
        Long taskId = request.getTaskId();
        RequestResult requestResult = sNetworkRespCreator.createRequestResult(taskId, response);
        moveRequestToFinishedCollection(taskId, requestResult);
    }

    /**
     * This method is called when the OptionsRequest retrieves the capabilities from cache.
     */
    private void handleCachedCapabilityUpdated(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        Long taskId = request.getTaskId();
        List<RcsContactUceCapability> cachedCapList = response.getCachedContactCapability();
        logd("handleCachedCapabilityUpdated: taskId=" + taskId + ", CapRequestResp=" + response);

        if (cachedCapList.isEmpty()) {
            return;
        }

        // Trigger the capabilities updated callback.
        triggerCapabilitiesReceivedCallback(cachedCapList);
        response.removeCachedContactCapabilities();
    }

    /**
     * This method is called when all the capabilities can be retrieved from the cached and it does
     * not need to request capabilities from the network.
     */
    private void handleNoNeedRequestFromNetwork(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        logd("handleNoNeedRequestFromNetwork: " + response.toString());

        // Finish this request.
        request.onFinish();

        // Remove this request from the activated collection and notify RequestManager.
        long taskId = request.getTaskId();
        RequestResult requestResult = sNotNeedRequestFromNetworkCreator.createRequestResult(taskId,
                response);
        moveRequestToFinishedCollection(taskId, requestResult);
    }

    /**
     * This method is called when the framework does not receive receive the result for
     * capabilities request.
     */
    private void handleRequestTimeout(OptionsRequest request) {
        CapabilityRequestResponse response = request.getRequestResponse();
        logd("handleRequestTimeout: " + response.toString());

        // Finish this request.
        request.onFinish();

        // Remove this request from the activated collection and notify RequestManager.
        long taskId = request.getTaskId();
        RequestResult requestResult = sRequestTimeoutCreator.createRequestResult(taskId,
                response);
        moveRequestToFinishedCollection(taskId, requestResult);
    }

    /**
     * Trigger the capabilities updated callback.
     */
    private void triggerCapabilitiesReceivedCallback(List<RcsContactUceCapability> capList) {
        try {
            logd("triggerCapabilitiesCallback: size=" + capList.size());
            mCapabilitiesCallback.onCapabilitiesReceived(capList);
        } catch (RemoteException e) {
            logw("triggerCapabilitiesCallback exception: " + e);
        } finally {
            logd("triggerCapabilitiesCallback: done");
        }
    }

    /**
     * Trigger the onComplete callback to notify the request is completed.
     */
    private void triggerCompletedCallback() {
        try {
            logd("triggerCompletedCallback");
            mCapabilitiesCallback.onComplete();
        } catch (RemoteException e) {
            logw("triggerCompletedCallback exception: " + e);
        } finally {
            logd("triggerCompletedCallback: done");
        }
    }

    /**
     * Trigger the onError callback to notify the request is failed.
     */
    private void triggerErrorCallback(int errorCode, long retryAfterMillis) {
        try {
            logd("triggerErrorCallback: errorCode=" + errorCode + ", retry=" + retryAfterMillis);
            mCapabilitiesCallback.onError(errorCode, retryAfterMillis);
        } catch (RemoteException e) {
            logw("triggerErrorCallback exception: " + e);
        } finally {
            logd("triggerErrorCallback: done");
        }
    }

    private void checkAndFinishRequestCoordinator() {
        synchronized (mCollectionLock) {
            // Return because there are requests running.
            if (!mActivatedRequests.isEmpty()) {
                return;
            }

            // All the requests has finished, find the request which has the max retryAfter time.
            // If the result is empty, it means all the request are success.
            Optional<RequestResult> optRequestResult =
                    mFinishedRequests.values().stream()
                            .filter(result -> !result.isRequestSuccess())
                            .max(Comparator.comparingLong(result ->
                                    result.getRetryMillis().orElse(-1L)));

            // Trigger the callback
            if (optRequestResult.isPresent()) {
                RequestResult result = optRequestResult.get();
                int errorCode = result.getErrorCode().orElse(DEFAULT_ERROR_CODE);
                long retryAfter = result.getRetryMillis().orElse(0L);
                triggerErrorCallback(errorCode, retryAfter);
            } else {
                triggerCompletedCallback();
            }

            // Notify UceRequestManager to remove this instance from the collection.
            mRequestManagerCallback.notifyRequestCoordinatorFinished(mCoordinatorId);

            logd("checkAndFinishRequestCoordinator(OptionsRequest) done, id=" + mCoordinatorId);
        }
    }

    @VisibleForTesting
    public Collection<UceRequest> getActivatedRequest() {
        return mActivatedRequests.values();
    }

    @VisibleForTesting
    public Collection<RequestResult> getFinishedRequest() {
        return mFinishedRequests.values();
    }
}
