/*
 * Copyright 2017 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.server.location;

import android.hardware.contexthub.V1_0.IContexthub;
import android.hardware.contexthub.V1_0.Result;
import android.hardware.contexthub.V1_0.TransactionResult;
import android.hardware.location.ContextHubTransaction;
import android.hardware.location.IContextHubTransactionCallback;
import android.hardware.location.NanoAppBinary;
import android.hardware.location.NanoAppState;
import android.os.RemoteException;
import android.util.Log;

import java.util.ArrayDeque;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Manages transactions at the Context Hub Service.
 *
 * This class maintains a queue of transaction requests made to the ContextHubService by clients,
 * and executes them through the Context Hub. At any point in time, either the transaction queue is
 * empty, or there is a pending transaction that is waiting for an asynchronous response from the
 * hub. This class also handles synchronous errors and timeouts of each transaction.
 *
 * @hide
 */
/* package */ class ContextHubTransactionManager {
    private static final String TAG = "ContextHubTransactionManager";

    /*
     * Maximum number of transaction requests that can be pending at a time
     */
    private static final int MAX_PENDING_REQUESTS = 10;

    /*
     * The proxy to talk to the Context Hub
     */
    private final IContexthub mContextHubProxy;

    /*
     * The manager for all clients for the service.
     */
    private final ContextHubClientManager mClientManager;

    /*
     * A queue containing the current transactions
     */
    private final ArrayDeque<ContextHubServiceTransaction> mTransactionQueue = new ArrayDeque<>();

    /*
     * The next available transaction ID
     */
    private final AtomicInteger mNextAvailableId = new AtomicInteger();

    /*
     * An executor and the future object for scheduling timeout timers
     */
    private final ScheduledThreadPoolExecutor mTimeoutExecutor = new ScheduledThreadPoolExecutor(1);
    private ScheduledFuture<?> mTimeoutFuture = null;

    /* package */ ContextHubTransactionManager(
            IContexthub contextHubProxy, ContextHubClientManager clientManager) {
        mContextHubProxy = contextHubProxy;
        mClientManager = clientManager;
    }

    /**
     * Creates a transaction for loading a nanoapp.
     *
     * @param contextHubId       the ID of the hub to load the nanoapp to
     * @param nanoAppBinary      the binary of the nanoapp to load
     * @param onCompleteCallback the client on complete callback
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createLoadTransaction(
            int contextHubId, NanoAppBinary nanoAppBinary,
            IContextHubTransactionCallback onCompleteCallback) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_LOAD_NANOAPP) {
            @Override
            /* package */ int onTransact() {
                android.hardware.contexthub.V1_0.NanoAppBinary hidlNanoAppBinary =
                        ContextHubServiceUtil.createHidlNanoAppBinary(nanoAppBinary);
                try {
                    return mContextHubProxy.loadNanoApp(
                            contextHubId, hidlNanoAppBinary, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to load nanoapp with ID 0x" +
                            Long.toHexString(nanoAppBinary.getNanoAppId()));
                    return Result.UNKNOWN_FAILURE;
                }
            }

            @Override
            /* package */ void onTimeout() {
                onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT);
            }

            @Override
            /* package */ void onTransactionComplete(int result) {
                try {
                    onCompleteCallback.onTransactionComplete(result);
                    if (result == Result.OK) {
                        mClientManager.onNanoAppLoaded(contextHubId, nanoAppBinary.getNanoAppId());
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while calling client onTransactionComplete");
                }
            }
        };
    }

    /**
     * Creates a transaction for unloading a nanoapp.
     *
     * @param contextHubId       the ID of the hub to load the nanoapp to
     * @param nanoAppId          the ID of the nanoapp to unload
     * @param onCompleteCallback the client on complete callback
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createUnloadTransaction(
            int contextHubId, long nanoAppId, IContextHubTransactionCallback onCompleteCallback) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_UNLOAD_NANOAPP) {
            @Override
            /* package */ int onTransact() {
                try {
                    return mContextHubProxy.unloadNanoApp(
                            contextHubId, nanoAppId, this.getTransactionId());
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to unload nanoapp with ID 0x" +
                            Long.toHexString(nanoAppId));
                    return Result.UNKNOWN_FAILURE;
                }
            }

            @Override
            /* package */ void onTimeout() {
                onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT);
            }

            @Override
            /* package */ void onTransactionComplete(int result) {
                try {
                    onCompleteCallback.onTransactionComplete(result);
                    if (result == Result.OK) {
                        mClientManager.onNanoAppUnloaded(contextHubId, nanoAppId);
                    }
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while calling client onTransactionComplete");
                }
            }
        };
    }

    /**
     * Creates a transaction for querying for a list of nanoapps.
     *
     * @param contextHubId       the ID of the hub to query
     * @param onCompleteCallback the client on complete callback
     * @return the generated transaction
     */
    /* package */ ContextHubServiceTransaction createQueryTransaction(
            int contextHubId, IContextHubTransactionCallback onCompleteCallback) {
        return new ContextHubServiceTransaction(
                mNextAvailableId.getAndIncrement(), ContextHubTransaction.TYPE_QUERY_NANOAPPS) {
            @Override
            /* package */ int onTransact() {
                try {
                    return mContextHubProxy.queryApps(contextHubId);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while trying to query for nanoapps");
                    return Result.UNKNOWN_FAILURE;
                }
            }

            @Override
            /* package */ void onTimeout() {
                onQueryResponse(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT,
                        Collections.emptyList());
            }

            @Override
            /* package */ void onQueryResponse(int result, List<NanoAppState> nanoAppStateList) {
                try {
                    onCompleteCallback.onQueryResponse(result, nanoAppStateList);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException while calling client onQueryComplete");
                }
            }
        };
    }

    /**
     * Adds a new transaction to the queue.
     *
     * If there was no pending transaction at the time, the transaction that was added will be
     * started in this method.
     *
     * @param transaction the transaction to add
     * @throws IllegalStateException if the queue is full
     */
    /* package */
    synchronized void addTransaction(
            ContextHubServiceTransaction transaction) throws IllegalStateException {
        if (mTransactionQueue.size() == MAX_PENDING_REQUESTS) {
            throw new IllegalStateException("Transaction transaction queue is full (capacity = "
                    + MAX_PENDING_REQUESTS + ")");
        }
        mTransactionQueue.add(transaction);

        if (mTransactionQueue.size() == 1) {
            startNextTransaction();
        }
    }

    /**
     * Handles a transaction response from a Context Hub.
     *
     * @param transactionId the transaction ID of the response
     * @param result        the result of the transaction
     */
    /* package */
    synchronized void onTransactionResponse(int transactionId, int result) {
        ContextHubServiceTransaction transaction = mTransactionQueue.peek();
        if (transaction == null) {
            Log.w(TAG, "Received unexpected transaction response (no transaction pending)");
            return;
        }
        if (transaction.getTransactionId() != transactionId) {
            Log.w(TAG, "Received unexpected transaction response (expected ID = "
                    + transaction.getTransactionId() + ", received ID = " + transactionId + ")");
            return;
        }

        transaction.onTransactionComplete(result);
        removeTransactionAndStartNext();
    }

    /**
     * Handles a query response from a Context Hub.
     *
     * @param nanoAppStateList the list of nanoapps included in the response
     */
    /* package */
    synchronized void onQueryResponse(List<NanoAppState> nanoAppStateList) {
        ContextHubServiceTransaction transaction = mTransactionQueue.peek();
        if (transaction == null) {
            Log.w(TAG, "Received unexpected query response (no transaction pending)");
            return;
        }
        if (transaction.getTransactionType() != ContextHubTransaction.TYPE_QUERY_NANOAPPS) {
            Log.w(TAG, "Received unexpected query response (expected " + transaction + ")");
            return;
        }

        transaction.onQueryResponse(TransactionResult.SUCCESS, nanoAppStateList);
        removeTransactionAndStartNext();
    }

    /**
     * Handles a hub reset event by stopping a pending transaction and starting the next.
     */
    /* package */
    synchronized void onHubReset() {
        ContextHubServiceTransaction transaction = mTransactionQueue.peek();
        if (transaction == null) {
            return;
        }

        removeTransactionAndStartNext();
    }

    /**
     * Pops the front transaction from the queue and starts the next pending transaction request.
     *
     * Removing elements from the transaction queue must only be done through this method. When a
     * pending transaction is removed, the timeout timer is cancelled and the transaction is marked
     * complete.
     *
     * It is assumed that the transaction queue is non-empty when this method is invoked, and that
     * the caller has obtained a lock on this ContextHubTransactionManager object.
     */
    private void removeTransactionAndStartNext() {
        mTimeoutFuture.cancel(false /* mayInterruptIfRunning */);

        ContextHubServiceTransaction transaction = mTransactionQueue.remove();
        transaction.setComplete();

        if (!mTransactionQueue.isEmpty()) {
            startNextTransaction();
        }
    }

    /**
     * Starts the next pending transaction request.
     *
     * Starting new transactions must only be done through this method. This method continues to
     * process the transaction queue as long as there are pending requests, and no transaction is
     * pending.
     *
     * It is assumed that the caller has obtained a lock on this ContextHubTransactionManager
     * object.
     */
    private void startNextTransaction() {
        int result = Result.UNKNOWN_FAILURE;
        while (result != Result.OK && !mTransactionQueue.isEmpty()) {
            ContextHubServiceTransaction transaction = mTransactionQueue.peek();
            result = transaction.onTransact();

            if (result == Result.OK) {
                Runnable onTimeoutFunc = () -> {
                    synchronized (this) {
                        if (!transaction.isComplete()) {
                            Log.d(TAG, transaction + " timed out");
                            transaction.onTimeout();

                            removeTransactionAndStartNext();
                        }
                    }
                };

                long timeoutSeconds = transaction.getTimeout(TimeUnit.SECONDS);
                mTimeoutFuture = mTimeoutExecutor.schedule(onTimeoutFunc, timeoutSeconds,
                        TimeUnit.SECONDS);
            } else {
                mTransactionQueue.remove();
            }
        }
    }
}
