/*
 * Copyright (C) 2011 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.tradefed.device;

import com.android.ddmlib.AdbCommandRejectedException;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.ShellCommandUnresponsiveException;
import com.android.ddmlib.TimeoutException;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Runs a command on a given device repeating as necessary until the action is canceled.
 * <p>
 * When the class is run, the command is run on the device in a separate thread and the output is
 * collected in a temporary host file.
 * </p><p>
 * This is done so:
 * </p><ul>
 * <li>if device goes permanently offline during a test, the log data is retained.</li>
 * <li>to capture more data than may fit in device's circular log.</li>
 * </ul>
 */
public class BackgroundDeviceAction extends Thread {
    private static final long ONLINE_POLL_INTERVAL_MS = 10 * 1000;
    private IShellOutputReceiver mReceiver;
    private ITestDevice mTestDevice;
    private String mCommand;
    private String mSerialNumber;
    private String mDescriptor;
    private boolean mIsCancelled;
    private int mLogStartDelay;

    /**
     * Creates a {@link BackgroundDeviceAction}
     *
     * @param command the command to run
     * @param descriptor the description of the command. For logging only.
     * @param device the device to run the command on
     * @param receiver the receiver for collecting the output of the command
     * @param startDelay the delay to wait after the device becomes online
     */
    public BackgroundDeviceAction(String command, String descriptor, ITestDevice device,
            IShellOutputReceiver receiver, int startDelay) {
        mCommand = command;
        mDescriptor = descriptor;
        mSerialNumber = device.getSerialNumber();
        mTestDevice = device;
        mReceiver = receiver;
        mLogStartDelay = startDelay;
        // don't keep VM open if this thread is still running
        setDaemon(true);
    }

    /**
     * {@inheritDoc}
     * <p>
     * Repeats the command until canceled.
     * </p>
     */
    @Override
    public void run() {
        String separator = String.format(
                "========== beginning of new [%s] output ==========\n", mDescriptor);
        while (!isCancelled()) {
            if (mLogStartDelay > 0) {
                CLog.d("Sleep for %d before starting %s for %s.", mLogStartDelay, mDescriptor,
                        mSerialNumber);
                getRunUtil().sleep(mLogStartDelay);
            }
            blockUntilOnlineNoThrow();
            // check again if the operation has been cancelled after the wait for online
            if (isCancelled()) {
                break;
            }
            CLog.d("Starting %s for %s.", mDescriptor, mSerialNumber);
            mReceiver.addOutput(separator.getBytes(), 0, separator.length());
            try {
                mTestDevice.getIDevice().executeShellCommand(mCommand, mReceiver,
                        0, TimeUnit.MILLISECONDS);
            } catch (TimeoutException e) {
                recoverDevice(e.getClass().getName());
            } catch (AdbCommandRejectedException e) {
                recoverDevice(e.getClass().getName());
            } catch (ShellCommandUnresponsiveException e) {
                recoverDevice(e.getClass().getName());
            } catch (IOException e) {
                recoverDevice(e.getClass().getName());
            }
        }
    }

    private void recoverDevice(String exceptionType) {
        CLog.d("%s while running %s on %s. May see duplicated content in log.", exceptionType,
                mDescriptor, mSerialNumber);

        // Make sure we haven't been cancelled before we sleep for a long time
        if (isCancelled()) {
            return;
        }

        // sleep a small amount for device to settle
        getRunUtil().sleep(5 * 1000);

        // wait a long time for device to be online
        try {
            mTestDevice.waitForDeviceOnline(10 * 60 * 1000);
        } catch (DeviceNotAvailableException e) {
            CLog.w("Device %s not online", mSerialNumber);
        }
    }

    /**
     * Cancels the command.
     */
    public synchronized void cancel() {
        mIsCancelled = true;
        interrupt();
    }

    /**
     * If the command is cancelled.
     */
    public synchronized boolean isCancelled() {
        return mIsCancelled;
    }

    /**
     * Get the {@link RunUtil} instance to use.
     * <p/>
     * Exposed for unit testing.
     */
    IRunUtil getRunUtil() {
        return RunUtil.getDefault();
    }

    private void blockUntilOnlineNoThrow() {
        CLog.d("Waiting for device %s online before starting.", mSerialNumber);
        while (!isCancelled()) {
            if (!TestDeviceState.ONLINE.equals(mTestDevice.getDeviceState())) {
                getRunUtil().sleep(ONLINE_POLL_INTERVAL_MS);
            } else {
                CLog.d("Device %s now online.", mSerialNumber);
                break;
            }
        }
    }
}
