/*
 * Copyright (C) 2019 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.uicd.tests;

import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.FileInputStreamSource;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.TestDescription;
import com.android.tradefed.testtype.IMultiDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.MultiMap;
import com.android.tradefed.util.RunUtil;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 * The class enables user to run their pre-recorded UICD tests on tradefed. Go to
 * https://github.com/google/android-uiconductor/releases/tag/v0.1.1 to download the uicd_cli.tar.gz
 * and extract the jar and apks required for the tests. Please look at the sample xmls in
 * res/config/uicd to configure your tests.
 */
public class UiConductorTest implements IMultiDeviceTest, IRemoteTest {

    @Option(
        name = "uicd-cli-jar",
        description = "The cli jar that runs the user provided tests in commandline",
        importance = Importance.IF_UNSET
    )
    private File cliJar;

    @Option(
        name = "commandline-action-executable",
        description =
                "the filesystem path of the binaries that are ran through command line actions on UICD. Can be repeated.",
        importance = Importance.IF_UNSET
    )
    private Collection<File> binaries = new ArrayList<File>();

    @Option(
        name = "global-variables",
        description = "Global variable (uicd_key1=value1,uicd_key2=value2)",
        importance = Importance.ALWAYS
    )
    private MultiMap<String, String> globalVariables = new MultiMap<>();

    @Option(
        name = "play-mode",
        description = "Play Mode (SINGLE|MULTIDEVICE|PLAYALL).",
        importance = Importance.ALWAYS
    )
    private String playMode = "SINGLE";

    @Option(name = "test-name", description = "Name of the test.", importance = Importance.ALWAYS)
    private String testName = "Your test results are here";

    // Same key can have multiple test files because global-variables can be referenced using the
    // that particular key and shared across different tests.
    // Refer res/config/uicd/uiconductor-globalvariable-sample.xml for more information.
    @Option(
        name = "uicd-test",
        description =
                "the filesystem path of the json test files or directory of multiple json test files that needs to be run on devices. Can be repeated.",
        importance = Importance.IF_UNSET
    )
    private MultiMap<String, File> uicdTest = new MultiMap<>();

    @Option(
        name = "test-timeout",
        description = "Time out for each test.",
        importance = Importance.IF_UNSET
    )
    private int testTimeout = 1800000;

    private static final String BINARY_RELATIVE_PATH = "binary";

    private static final String OUTPUT_RELATIVE_PATH = "output";

    private static final String TESTS_RELATIVE_PATH = "tests";

    private static final String RESULTS_RELATIVE_PATH = "result";

    private static final String OPTION_SYMBOL = "-";
    private static final String INPUT_OPTION_SHORT_NAME = "i";
    private static final String OUTPUT_OPTION_SHORT_NAME = "o";
    private static final String DEVICES_OPTION_SHORT_NAME = "d";
    private static final String MODE_OPTION_SHORT_NAME = "m";
    private static final String GLOBAL_VARIABLE_OPTION_SHORT_NAME = "g";

    private static final String CHILDRENRESULT_ATTRIBUTE = "childrenResult";
    private static final String PLAYSTATUS_ATTRIBUTE = "playStatus";
    private static final String VALIDATIONDETAILS_ATTRIBUTE = "validationDetails";

    private static final String EXECUTABLE = "u+x";

    private static String baseFilePath = System.getenv("HOME") + "/tmp/uicd-on-tf";

    Map<ITestDevice, IBuildInfo> deviceInfos;

    @Override
    public void setDeviceInfos(Map<ITestDevice, IBuildInfo> deviceInfos) {
        this.deviceInfos = deviceInfos;
    }

    @Override
    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
        CLog.i("Starting the UIConductor tests:\n");
        String runId = UUID.randomUUID().toString();
        baseFilePath = Paths.get(baseFilePath, runId).toString();
        String jarFileDir = Paths.get(baseFilePath, BINARY_RELATIVE_PATH).toString();
        String testFilesDir = Paths.get(baseFilePath, TESTS_RELATIVE_PATH).toString();
        String binaryFilesDir = Paths.get(baseFilePath).toString();
        File jarFile;
        MultiMap<String, File> copiedTestFileMap = new MultiMap<>();
        if (cliJar == null || !cliJar.exists()) {
            CLog.e("Unable to fetch provided binary.\n");
            return;
        }
        try {
            jarFile = copyFile(cliJar.getAbsolutePath(), jarFileDir);
            FileUtil.chmod(jarFile, EXECUTABLE);

            for (Map.Entry<String, File> testFileOrDirEntry : uicdTest.entries()) {
                copiedTestFileMap.putAll(
                        copyFile(
                                testFileOrDirEntry.getKey(),
                                testFileOrDirEntry.getValue().getAbsolutePath(),
                                testFilesDir));
            }

            for (File binaryFile : binaries) {
                File binary = copyFile(binaryFile.getAbsolutePath(), binaryFilesDir);
                FileUtil.chmod(binary, EXECUTABLE);
            }
        } catch (IOException ex) {
            throw new DeviceNotAvailableException(ex.getMessage());
        }

        RunUtil rUtil = new RunUtil();
        rUtil.setWorkingDir(new File(baseFilePath));
        long runStartTime = System.currentTimeMillis();
        listener.testRunStarted(testName, copiedTestFileMap.values().size());
        for (Map.Entry<String, File> testFileEntry : copiedTestFileMap.entries()) {
            runTest(
                    listener,
                    rUtil,
                    jarFile,
                    testFileEntry.getKey(),
                    testFileEntry.getValue().getName());
        }

        listener.testRunEnded(
                System.currentTimeMillis() - runStartTime, new HashMap<String, String>());
        FileUtil.recursiveDelete(new File(baseFilePath));
        CLog.i("Finishing the ui conductor tests\n");
    }

    public void runTest(
            ITestInvocationListener listener,
            RunUtil rUtil,
            File jarFile,
            String key,
            String testFileName) {
        TestDescription testDesc =
                new TestDescription(this.getClass().getSimpleName(), testFileName);
        listener.testStarted(testDesc, System.currentTimeMillis());

        String testId = UUID.randomUUID().toString();
        CommandResult cmndRes =
                rUtil.runTimedCmd(testTimeout, getCommand(jarFile, testFileName, testId, key));
        logInfo(testId, "STD", cmndRes.getStdout());
        logInfo(testId, "ERR", cmndRes.getStderr());

        File resultsFile =
                new File(
                        Paths.get(
                                        baseFilePath,
                                        OUTPUT_RELATIVE_PATH,
                                        testId,
                                        RESULTS_RELATIVE_PATH,
                                        "action_execution_result")
                                .toString());

        if (resultsFile.exists()) {
            try {
                String content = FileUtil.readStringFromFile(resultsFile);
                JSONObject result = new JSONObject(content);
                List<String> errors = new ArrayList<>();
                errors = parseResult(errors, result);
                if (!errors.isEmpty()) {
                    listener.testFailed(testDesc, errors.get(0));
                    CLog.i("Test %s failed due to following errors: \n", testDesc.getTestName());
                    for (String error : errors) {
                        CLog.i(error + "\n");
                    }
                }
            } catch (IOException | JSONException e) {
                CLog.e(e);
            }
            String testResultFileName = testFileName + "_action_execution_result";
            try (InputStreamSource iSSource = new FileInputStreamSource(resultsFile)) {
                listener.testLog(testResultFileName, LogDataType.TEXT, iSSource);
            }
        }
        listener.testEnded(testDesc, System.currentTimeMillis(), new HashMap<String, String>());
    }

    private void logInfo(String testId, String cmdOutputType, String content) {
        CLog.i(
                "==========================="
                        + cmdOutputType
                        + " logs for "
                        + testId
                        + " starts===========================\n");
        CLog.i(content);
        CLog.i(
                "==========================="
                        + cmdOutputType
                        + " logs for "
                        + testId
                        + " ends===========================\n");
    }

    private List<String> parseResult(List<String> errors, JSONObject result) throws JSONException {

        if (result != null) {
            if (result.has(CHILDRENRESULT_ATTRIBUTE)) {
                JSONArray childResults = result.getJSONArray(CHILDRENRESULT_ATTRIBUTE);
                for (int i = 0; i < childResults.length(); i++) {
                    errors = parseResult(errors, childResults.getJSONObject(i));
                }
            }

            if (result.has(PLAYSTATUS_ATTRIBUTE)
                    && result.getString(PLAYSTATUS_ATTRIBUTE).equalsIgnoreCase("FAIL")) {
                if (result.has(VALIDATIONDETAILS_ATTRIBUTE)) {
                    errors.add(result.getString(VALIDATIONDETAILS_ATTRIBUTE));
                }
            }
        }
        return errors;
    }

    private File copyFile(String srcFilePath, String destDirPath) throws IOException {
        File srcFile = new File(srcFilePath);
        File destDir = new File(destDirPath);
        if (srcFile.isDirectory()) {
            for (File file : srcFile.listFiles()) {
                copyFile(file.getAbsolutePath(), Paths.get(destDirPath, file.getName()).toString());
            }
        }
        if (!destDir.isDirectory() && !destDir.mkdirs()) {
            throw new IOException(
                    String.format("Could not create directory %s", destDir.getAbsolutePath()));
        }
        File destFile = new File(Paths.get(destDir.toString(), srcFile.getName()).toString());
        FileUtil.copyFile(srcFile, destFile);
        return destFile;
    }

    // copy file to destDirPath while maintaining a map of key that refers to that src file
    private MultiMap<String, File> copyFile(String key, String srcFilePath, String destDirPath)
            throws IOException {
        MultiMap<String, File> copiedTestFileMap = new MultiMap<>();
        File srcFile = new File(srcFilePath);
        File destDir = new File(destDirPath);
        if (srcFile.isDirectory()) {
            for (File file : srcFile.listFiles()) {
                copiedTestFileMap.putAll(
                        copyFile(
                                key,
                                file.getAbsolutePath(),
                                Paths.get(destDirPath, file.getName()).toString()));
            }
        }
        if (!destDir.isDirectory() && !destDir.mkdirs()) {
            throw new IOException(
                    String.format("Could not create directory %s", destDir.getAbsolutePath()));
        }
        if (srcFile.isFile()) {
            File destFile = new File(Paths.get(destDir.toString(), srcFile.getName()).toString());
            FileUtil.copyFile(srcFile, destFile);
            copiedTestFileMap.put(key, destFile);
        }
        return copiedTestFileMap;
    }

    private String getTestFilesArgsForUicdBin(String testFilesDir, String filename) {
        return (!testFilesDir.isEmpty() && !filename.isEmpty())
                ? Paths.get(testFilesDir, filename).toString()
                : "";
    }

    private String getOutFilesArgsForUicdBin(String outFilesDir) {
        return !outFilesDir.isEmpty() ? outFilesDir : "";
    }

    private String getPlaymodeArgForUicdBin() {
        return !playMode.isEmpty() ? playMode : "";
    }

    private String getDevIdsArgsForUicdBin() {
        List<String> devIds = new ArrayList<>();
        for (ITestDevice device : deviceInfos.keySet()) {
            devIds.add(device.getSerialNumber());
        }
        return String.join(",", devIds);
    }

    private String[] getCommand(File jarFile, String testFileName, String testId, String key) {
        List<String> command = new ArrayList<>();
        command.add("java");
        command.add("-jar");
        command.add(jarFile.getAbsolutePath());
        if (!getTestFilesArgsForUicdBin(TESTS_RELATIVE_PATH, testFileName).isEmpty()) {
            command.add(OPTION_SYMBOL + INPUT_OPTION_SHORT_NAME);
            command.add(getTestFilesArgsForUicdBin(TESTS_RELATIVE_PATH, testFileName));
        }
        if (!getOutFilesArgsForUicdBin(OUTPUT_RELATIVE_PATH + "/" + testId).isEmpty()) {
            command.add(OPTION_SYMBOL + OUTPUT_OPTION_SHORT_NAME);
            command.add(getOutFilesArgsForUicdBin(OUTPUT_RELATIVE_PATH + "/" + testId));
        }
        if (!getPlaymodeArgForUicdBin().isEmpty()) {
            command.add(OPTION_SYMBOL + MODE_OPTION_SHORT_NAME);
            command.add(getPlaymodeArgForUicdBin());
        }
        if (!getDevIdsArgsForUicdBin().isEmpty()) {
            command.add(OPTION_SYMBOL + DEVICES_OPTION_SHORT_NAME);
            command.add(getDevIdsArgsForUicdBin());
        }
        if (globalVariables.containsKey(key)) {
            command.add(OPTION_SYMBOL + GLOBAL_VARIABLE_OPTION_SHORT_NAME);
            command.add(String.join(",", globalVariables.get(key)));
        }
        return command.toArray(new String[] {});
    }
}
