/*
 * 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 com.android.cts.jank;

import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.util.HostReportLog;
import com.android.cts.util.ResultType;
import com.android.cts.util.ResultUnit;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IBuildReceiver;

import java.io.File;
import java.util.HashMap;
import java.util.Scanner;

public class CtsHostJankTest extends DeviceTestCase implements IAbiReceiver, IBuildReceiver {

    private static final String TAG = CtsHostJankTest.class.getSimpleName();
    private static final String DEVICE_LOCATION = "/data/local/tmp/";
    // FIXME uiautomator is deprecated and does not support --abi flag
    private static final String RUN_UI_AUTOMATOR_CMD = "uiautomator runtest %s -c %s";
    private final String mHostTestClass;
    private final String mDeviceTestClass;
    private final String mJarName;
    private final String mJarPath;
    protected ITestDevice mDevice;
    protected CtsBuildHelper mBuild;
    protected IAbi mAbi;

    public CtsHostJankTest(String jarName, String deviceTestClass, String hostTestClass) {
        this.mHostTestClass = hostTestClass;
        this.mDeviceTestClass = deviceTestClass;
        this.mJarName = jarName;
        this.mJarPath = DEVICE_LOCATION + jarName;
    }

    @Override
    public void setAbi(IAbi abi) {
        mAbi = abi;
    }

    @Override
    public void setBuild(IBuildInfo buildInfo) {
        mBuild = CtsBuildHelper.createBuildHelper(buildInfo);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mDevice = getDevice();
        // Push jar to device.
        File jarFile = mBuild.getTestApp(mJarName);
        boolean result = mDevice.pushFile(jarFile, mJarPath);
        assertTrue("Failed to push file to " + mJarPath, result);
    }

    @Override
    protected void tearDown() throws Exception {
        // Delete jar from device.
        mDevice.executeShellCommand("rm " + mJarPath);
        super.tearDown();
    }

    public void runUiAutomatorTest(String testName) throws Exception {
        // Delete any existing result files
        mDevice.executeShellCommand("rm -r " + DEVICE_LOCATION + "*.txt");

        // Run ui automator test.
        mDevice.executeShellCommand(
                String.format(RUN_UI_AUTOMATOR_CMD, mJarName, mDeviceTestClass + "#" + testName),
                new IShellOutputReceiver() {
                    private StringBuilder sb = new StringBuilder();

                    @Override
                    public void addOutput(byte[] data, int offset, int length) {
                        byte[] raw = new byte[length];
                        for (int i = 0; i < length; i++) {
                            raw[i] = data[i + offset];
                        }
                        sb.append(new String(raw));
                    }

                    @Override
                    public void flush() {
                        Log.logAndDisplay(LogLevel.INFO, TAG, sb.toString());
                    }

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

        // Pull result file across
        File result = mDevice.pullFile(DEVICE_LOCATION + "UiJankinessTestsOutput.txt");
        assertNotNull("Couldn't get result file", result);
        // Parse result file
        Scanner in = new Scanner(result);
        HashMap<String, Double> results = new HashMap<String, Double>(4);
        while (in.hasNextLine()) {
            String[] parts = in.nextLine().split(":");
            if (parts.length == 2) {
                results.put(parts[0], Double.parseDouble(parts[1]));
            }
        }
        in.close();
        Log.logAndDisplay(LogLevel.INFO, TAG, "Results: " + results);
        assertEquals("Could not parse the results file: ", 4, results.size());

        double avgNumJanks = results.get("average number of jankiness");
        double maxNumJanks = results.get("max number of jankiness");
        double avgFrameRate = results.get("average frame rate");
        double avgMaxAccFrames = results.get("average of max accumulated frames");

        // Create and deliver the report.
        HostReportLog report = new HostReportLog(mDevice.getSerialNumber(), mAbi.getName(),
                mHostTestClass + "#" + testName);
        report.printValue(
                "Average Frame Rate", avgFrameRate, ResultType.HIGHER_BETTER, ResultUnit.COUNT);
        report.printValue("Average of Maximum Accumulated Frames", avgMaxAccFrames,
                ResultType.LOWER_BETTER, ResultUnit.COUNT);
        report.printValue(
                "Maximum Number of Janks", maxNumJanks, ResultType.LOWER_BETTER, ResultUnit.COUNT);
        report.printSummary(
                "Average Number of Janks", avgNumJanks, ResultType.LOWER_BETTER, ResultUnit.SCORE);
        report.deliverReportToHost();
    }

}
