/*
 * Copyright (C) 2013 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 android.hardware.cts.helpers.sensoroperations;

import junit.framework.Assert;

import android.hardware.cts.helpers.SensorStats;
import android.os.SystemClock;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * A {@link SensorOperation} that executes a set of children {@link SensorOperation}s in parallel.
 * The children are run in parallel but are given an index label in the order they are added. This
 * class can be combined to compose complex {@link SensorOperation}s.
 */
public class ParallelSensorOperation extends SensorOperation {
    public static final String STATS_TAG = "parallel";

    private final ArrayList<SensorOperation> mOperations = new ArrayList<>();
    private final Long mTimeout;
    private final TimeUnit mTimeUnit;

    /**
     * Constructor for the {@link ParallelSensorOperation} without a timeout.
     */
    // TODO: sensor tests must always provide a timeout to prevent tests from running forever
    public ParallelSensorOperation() {
        mTimeout = null;
        mTimeUnit = null;
    }

    /**
     * Constructor for the {@link ParallelSensorOperation} with a timeout.
     */
    public ParallelSensorOperation(long timeout, TimeUnit timeUnit) {
        if (timeUnit == null) {
            throw new IllegalArgumentException("Arguments cannot be null");
        }
        mTimeout = timeout;
        mTimeUnit = timeUnit;
    }

    /**
     * Add a set of {@link SensorOperation}s.
     */
    public void add(SensorOperation ... operations) {
        for (SensorOperation operation : operations) {
            if (operation == null) {
                throw new IllegalArgumentException("Arguments cannot be null");
            }
            mOperations.add(operation);
        }
    }

    /**
     * Executes the {@link SensorOperation}s in parallel. If an exception occurs one or more
     * operations, the first exception will be thrown once all operations are completed.
     */
    @Override
    public void execute() throws InterruptedException {
        int operationsCount = mOperations.size();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                operationsCount,
                operationsCount,
                1 /* keepAliveTime */,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>());
        executor.allowCoreThreadTimeOut(true);
        executor.prestartAllCoreThreads();

        ArrayList<Future<SensorOperation>> futures = new ArrayList<>();
        for (final SensorOperation operation : mOperations) {
            Future<SensorOperation> future = executor.submit(new Callable<SensorOperation>() {
                @Override
                public SensorOperation call() throws Exception {
                    operation.execute();
                    return operation;
                }
            });
            futures.add(future);
        }

        Long executionTimeNs = null;
        if (mTimeout != null) {
            executionTimeNs = SystemClock.elapsedRealtimeNanos()
                    + TimeUnit.NANOSECONDS.convert(mTimeout, mTimeUnit);
        }

        boolean hasAssertionErrors = false;
        ArrayList<Integer> timeoutIndices = new ArrayList<>();
        ArrayList<Throwable> exceptions = new ArrayList<>();
        for (int i = 0; i < operationsCount; ++i) {
            Future<SensorOperation> future = futures.get(i);
            try {
                SensorOperation operation = getFutureResult(future, executionTimeNs);
                addSensorStats(STATS_TAG, i, operation.getStats());
            } catch (ExecutionException e) {
                // extract the exception thrown by the worker thread
                Throwable cause = e.getCause();
                hasAssertionErrors |= (cause instanceof AssertionError);
                exceptions.add(e.getCause());
                addSensorStats(STATS_TAG, i, mOperations.get(i).getStats());
            } catch (TimeoutException e) {
                // we log, but we also need to interrupt the operation to terminate cleanly
                timeoutIndices.add(i);
                future.cancel(true /* mayInterruptIfRunning */);
            } catch (InterruptedException e) {
                // clean-up after ourselves by interrupting all the worker threads, and propagate
                // the interruption status, so we stop the outer loop as well
                executor.shutdownNow();
                throw e;
            }
        }

        String summary = getSummaryMessage(exceptions, timeoutIndices);
        if (hasAssertionErrors) {
            getStats().addValue(SensorStats.ERROR, summary);
        }
        if (!exceptions.isEmpty() || !timeoutIndices.isEmpty()) {
            Assert.fail(summary);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ParallelSensorOperation clone() {
        ParallelSensorOperation operation = new ParallelSensorOperation();
        for (SensorOperation subOperation : mOperations) {
            operation.add(subOperation.clone());
        }
        return operation;
    }

    /**
     * Helper method that waits for a {@link Future} to complete, and returns its result.
     */
    private SensorOperation getFutureResult(Future<SensorOperation> future, Long timeoutNs)
            throws ExecutionException, TimeoutException, InterruptedException {
        if (timeoutNs == null) {
            return future.get();
        }
        // cap timeout to 1ns so that join doesn't block indefinitely
        long waitTimeNs = Math.max(timeoutNs - SystemClock.elapsedRealtimeNanos(), 1);
        return future.get(waitTimeNs, TimeUnit.NANOSECONDS);
    }

    /**
     * Helper method for joining the exception and timeout messages used in assertions.
     */
    private String getSummaryMessage(List<Throwable> exceptions, List<Integer> timeoutIndices) {
        StringBuilder sb = new StringBuilder();
        for (Throwable exception : exceptions) {
            sb.append(exception.toString()).append(", ");
        }

        if (!timeoutIndices.isEmpty()) {
            sb.append("Operation");
            if (timeoutIndices.size() != 1) {
                sb.append("s");
            }
            sb.append(" [");
            for (Integer index : timeoutIndices) {
                sb.append(index).append(", ");
            }
            sb.append("] timed out");
        }

        return sb.toString();
    }
}
