/*
 * Copyright (C) 2012 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.ide.eclipse.ddms.systrace;

import com.android.ddmlib.IDevice;
import com.android.ddmlib.IShellOutputReceiver;
import com.google.common.primitives.Bytes;

public class SystraceTask implements Runnable {
    private final IDevice mDevice;
    private final String mOptions;

    private volatile boolean mCancel;

    private final Object mLock = new Object();
    private String errorMessage;
    private boolean mTraceComplete;
    private byte[] mBuffer = new byte[1024];
    private int mDataLength = 0;

    public SystraceTask(IDevice device, String options) {
        mDevice = device;
        mOptions = options;
    }

    @Override
    public void run() {
        try {
            mDevice.executeShellCommand("atrace " + mOptions, new Receiver(), 0);
        } catch (Exception e) {
            synchronized (mLock) {
                errorMessage = "Unexpected error while running atrace on device: " + e;
            }
        }
    }

    public void cancel() {
        mCancel = true;
    }

    public String getError() {
        synchronized (mLock) {
            return errorMessage;
        }
    }

    public byte[] getAtraceOutput() {
        synchronized (mLock) {
            return mTraceComplete ? mBuffer : null;
        }
    }

    private class Receiver implements IShellOutputReceiver {
        @Override
        public void addOutput(byte[] data, int offset, int length) {
            synchronized (mLock) {
                if (mDataLength + length > mBuffer.length) {
                    mBuffer = Bytes.ensureCapacity(mBuffer, mDataLength + length + 1, 1024);
                }

                for (int i = 0; i < length; i++) {
                    mBuffer[mDataLength + i] = data[offset + i];
                }
                mDataLength += length;
            }
        }

        @Override
        public void flush() {
            synchronized (mLock) {
                // trim mBuffer to its final size
                byte[] copy = new byte[mDataLength];
                for (int i = 0; i < mDataLength; i++) {
                    copy[i] = mBuffer[i];
                }
                mBuffer = copy;

                mTraceComplete = true;
            }
        }

        @Override
        public boolean isCancelled() {
            return mCancel;
        }
    }
}
