/*
 * 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.targetprep;

import com.android.ddmlib.IDevice;
import com.android.tradefed.build.BuildInfoKey.BuildInfoFileKey;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.build.IDeviceBuildInfo;
import com.android.tradefed.command.remote.DeviceDescriptor;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.invoker.logger.InvocationMetricLogger;
import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.observatory.IDiscoverDependencies;
import com.android.tradefed.result.error.DeviceErrorIdentifier;
import com.android.tradefed.result.error.ErrorIdentifier;
import com.android.tradefed.result.error.InfraErrorIdentifier;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.testtype.IAbiReceiver;
import com.android.tradefed.testtype.IInvocationContextReceiver;
import com.android.tradefed.testtype.suite.ModuleDefinition;
import com.android.tradefed.util.AbiUtils;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.MultiMap;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A {@link ITargetPreparer} that attempts to push any number of files from any host path to any
 * device path.
 *
 * <p>Should be performed *after* a new build is flashed, and *after* DeviceSetup is run (if
 * enabled)
 */
@OptionClass(alias = "push-file")
public class PushFilePreparer extends BaseTargetPreparer
        implements IAbiReceiver, IInvocationContextReceiver, IDiscoverDependencies {
    private static final String MEDIA_SCAN_INTENT =
            "am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://%s "
                    + "--receiver-include-background";

    private IAbi mAbi;

    @Deprecated
    @Option(
        name = "push",
        description =
                "Deprecated. Please use push-file instead. A push-spec, formatted as "
                        + "'/localpath/to/srcfile.txt->/devicepath/to/destfile.txt' "
                        + "or '/localpath/to/srcfile.txt->/devicepath/to/destdir/'. "
                        + "May be repeated. The local path may be relative to the test cases "
                        + "build out directories "
                        + "($ANDROID_HOST_OUT_TESTCASES / $ANDROID_TARGET_OUT_TESTCASES)."
    )
    private Collection<String> mPushSpecs = new ArrayList<>();

    @Option(
            name = "push-file",
            description =
                    "A push-spec, specifying the local file to the path where it should be pushed"
                        + " on device. May be repeated. If multiple files are configured to be"
                        + " pushed to the same remote path, the latest one will be pushed.")
    private MultiMap<File, String> mPushFileSpecs = new MultiMap<>();

    @Option(
            name = "skip-abi-filtering",
            description =
                    "A bool to indicate we should or shouldn't skip files that match the "
                            + "architecture string name, e.g. x86, x86_64, arm64-v8. This "
                            + "is necessary when file or folder names match an architecture "
                            + "version but still need to be pushed to the device.")
    private boolean mSkipAbiFiltering = false;

    @Option(
            name = "backup-file",
            description =
                    "A key/value pair, the with key specifying a device file path to be backed up, "
                            + "and the value a device file path indicating where to save the file. "
                            + "During tear-down, the values will be executed in reverse, "
                            + "restoring the backup file location to the initial location. "
                            + "May be repeated.")
    private Map<String, String> mBackupFileSpecs = new LinkedHashMap<>();

    @Option(name="post-push", description=
            "A command to run on the device (with `adb shell (yourcommand)`) after all pushes " +
            "have been attempted.  Will not be run if a push fails with abort-on-push-failure " +
            "enabled.  May be repeated.")
    private Collection<String> mPostPushCommands = new ArrayList<>();

    @Option(name="abort-on-push-failure", description=
            "If false, continue if pushes fail.  If true, abort the Invocation on any failure.")
    private boolean mAbortOnFailure = true;

    @Option(name="trigger-media-scan", description=
            "After pushing files, trigger a media scan of external storage on device.")
    private boolean mTriggerMediaScan = false;

    @Option(
            name = "cleanup",
            description =
                    "Whether files pushed onto device should be cleaned up after test. Note that"
                        + " the preparer does not verify that files/directories have been deleted.")
    private boolean mCleanup = true;

    @Option(
            name = "remount-system",
            description =
                    "Remounts system partition to be writable "
                            + "so that files could be pushed there too")
    private boolean mRemountSystem = false;

    @Option(
            name = "remount-vendor",
            description =
                    "Remounts vendor partition to be writable "
                            + "so that files could be pushed there too")
    private boolean mRemountVendor = false;

    private Set<String> mFilesPushed = null;
    /** If the preparer is part of a module, we can use the test module name as a search criteria */
    private String mModuleName = null;

    /**
     * Helper method to only throw if mAbortOnFailure is enabled. Callers should behave as if this
     * method may return.
     */
    private void fail(String message, DeviceDescriptor descriptor, ErrorIdentifier identifier)
            throws TargetSetupError {
        if (shouldAbortOnFailure()) {
            throw new TargetSetupError(message, descriptor, identifier);
        } else {
            // Log the error and return
            CLog.w(message);
        }
    }

    /** Create the list of files to be pushed. */
    public final Map<String, File> getPushSpecs(ITestDevice device) throws TargetSetupError {
        Map<String, File> remoteToLocalMapping = new LinkedHashMap<>();
        for (String pushspec : mPushSpecs) {
            String[] pair = pushspec.split("->");
            if (pair.length != 2) {
                fail(
                        String.format("Invalid pushspec: '%s'", Arrays.asList(pair)),
                        device.getDeviceDescriptor(),
                        InfraErrorIdentifier.OPTION_CONFIGURATION_ERROR);
                continue;
            }
            remoteToLocalMapping.put(pair[1], new File(pair[0]));
        }
        // Push the file structure
        for (File local : mPushFileSpecs.keySet()) {
            for (String remoteLocation : mPushFileSpecs.get(local)) {
                remoteToLocalMapping.put(remoteLocation, local);
            }
        }
        return remoteToLocalMapping;
    }

    /** Whether or not to abort on push failure. */
    public boolean shouldAbortOnFailure() {
        return mAbortOnFailure;
    }

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

    /** {@inheritDoc} */
    @Override
    public IAbi getAbi() {
        return mAbi;
    }

    /** {@inheritDoc} */
    @Override
    public void setInvocationContext(IInvocationContext invocationContext) {
        if (invocationContext.getAttributes().get(ModuleDefinition.MODULE_NAME) != null) {
            // Only keep the module name
            mModuleName =
                    invocationContext.getAttributes().get(ModuleDefinition.MODULE_NAME).get(0);
        }
    }

    /**
     * Resolve relative file path via {@link IBuildInfo} and test cases directories.
     *
     * @param buildInfo the build artifact information
     * @param fileName relative file path to be resolved
     * @return the file from the build info or test cases directories
     */
    public File resolveRelativeFilePath(IBuildInfo buildInfo, String fileName) {
        File src = null;
        if (buildInfo != null) {
            src = buildInfo.getFile(fileName);
            if (src != null && src.exists()) {
                return src;
            }
        }
        if (buildInfo instanceof IDeviceBuildInfo) {
            IDeviceBuildInfo deviceBuild = (IDeviceBuildInfo) buildInfo;
            File testDir = deviceBuild.getTestsDir();
            List<File> scanDirs = new ArrayList<>();
            // If it exists, always look first in the ANDROID_TARGET_OUT_TESTCASES
            File targetTestCases = deviceBuild.getFile(BuildInfoFileKey.TARGET_LINKED_DIR);
            if (targetTestCases != null) {
                scanDirs.add(targetTestCases);
            }
            if (testDir != null) {
                scanDirs.add(testDir);
            }

            if (mModuleName != null) {
                // Use module name as a discriminant to find some files
                if (testDir != null) {
                    try {
                        File moduleDir =
                                FileUtil.findDirectory(
                                        mModuleName, scanDirs.toArray(new File[] {}));
                        if (moduleDir != null) {
                            // If the spec is pushing the module itself
                            if (mModuleName.equals(fileName)) {
                                // If that's the main binary generated by the target, we push the
                                // full directory
                                return moduleDir;
                            }
                            // Search the module directory if it exists use it in priority
                            src = FileUtil.findFile(fileName, null, moduleDir);
                            if (src != null) {
                                // Search again with filtering on ABI
                                File srcWithAbi = FileUtil.findFile(fileName, mAbi, moduleDir);
                                if (srcWithAbi != null
                                        && !srcWithAbi
                                                .getAbsolutePath()
                                                .startsWith(src.getAbsolutePath())) {
                                    // When multiple matches are found, return the one with matching
                                    // ABI unless src is its parent directory.
                                    return srcWithAbi;
                                }
                                return src;
                            }
                        } else {
                            CLog.d("Did not find any module directory for '%s'", mModuleName);
                        }

                    } catch (IOException e) {
                        CLog.w(
                                "Something went wrong while searching for the module '%s' "
                                        + "directory.",
                                mModuleName);
                    }
                }
            }
            // Search top-level matches
            for (File searchDir : scanDirs) {
                try {
                    Set<File> allMatch = FileUtil.findFilesObject(searchDir, fileName);
                    if (allMatch.size() > 1) {
                        CLog.d(
                                "Several match for filename '%s', searching for top-level match.",
                                fileName);
                        for (File f : allMatch) {
                            // Bias toward direct child / top level nodes
                            if (f.getParent().equals(searchDir.getAbsolutePath())) {
                                return f;
                            }
                        }
                    } else if (allMatch.size() == 1) {
                        return allMatch.iterator().next();
                    }
                } catch (IOException e) {
                    CLog.w("Failed to find test files from directory.");
                }
            }
            // Fall-back to searching everything
            try {
                // Search the full tests dir if no target dir is available.
                src = FileUtil.findFile(fileName, null, scanDirs.toArray(new File[] {}));
                if (src != null) {
                    // Search again with filtering on ABI
                    File srcWithAbi =
                            FileUtil.findFile(fileName, mAbi, scanDirs.toArray(new File[] {}));
                    if (srcWithAbi != null
                            && !srcWithAbi.getAbsolutePath().startsWith(src.getAbsolutePath())) {
                        // When multiple matches are found, return the one with matching
                        // ABI unless src is its parent directory.
                        return srcWithAbi;
                    }
                    return src;
                }
            } catch (IOException e) {
                CLog.w("Failed to find test files from directory.");
                src = null;
            }

            if (src == null && testDir != null) {
                // TODO(b/138416078): Once build dependency can be fixed and test required
                // APKs are all under the test module directory, we can remove this fallback
                // approach to do individual download from remote artifact.
                // Try to stage the files from remote zip files.
                src = buildInfo.stageRemoteFile(fileName, testDir);
                if (src != null) {
                    InvocationMetricLogger.addInvocationMetrics(
                            InvocationMetricKey.STAGE_UNDEFINED_DEPENDENCY, fileName);
                    try {
                        // Search again with filtering on ABI
                        File srcWithAbi = FileUtil.findFile(fileName, mAbi, testDir);
                        if (srcWithAbi != null
                                && !srcWithAbi
                                        .getAbsolutePath()
                                        .startsWith(src.getAbsolutePath())) {
                            // When multiple matches are found, return the one with matching
                            // ABI unless src is its parent directory.
                            return srcWithAbi;
                        }
                    } catch (IOException e) {
                        CLog.w("Failed to find test files with matching ABI from directory.");
                    }
                }
            }
        }
        return src;
    }

    /** {@inheritDoc} */
    @Override
    public void setUp(TestInformation testInfo)
            throws TargetSetupError, BuildError, DeviceNotAvailableException {
        mFilesPushed = new HashSet<>();
        ITestDevice device = testInfo.getDevice();
        if (mRemountSystem) {
            device.remountSystemWritable();
        }
        if (mRemountVendor) {
            device.remountVendorWritable();
        }

        // Backup files
        for (Map.Entry<String, String> entry : mBackupFileSpecs.entrySet()) {
            device.executeShellCommand(
                    "mv \"" + entry.getKey() + "\" \"" + entry.getValue() + "\"");
        }

        Map<String, File> remoteToLocalMapping = getPushSpecs(device);
        for (String remotePath : remoteToLocalMapping.keySet()) {
            File local = remoteToLocalMapping.get(remotePath);
            CLog.d("Trying to push local '%s' to remote '%s'", local.getPath(), remotePath);
            evaluatePushingPair(device, testInfo.getBuildInfo(), local, remotePath);
        }

        for (String command : mPostPushCommands) {
            device.executeShellCommand(command);
        }

        if (mTriggerMediaScan) {
            String mountPoint = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
            device.executeShellCommand(String.format(MEDIA_SCAN_INTENT, mountPoint));
        }
    }

    /** {@inheritDoc} */
    @Override
    public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException {
        ITestDevice device = testInfo.getDevice();
        if (!(e instanceof DeviceNotAvailableException) && mCleanup && mFilesPushed != null) {
            if (mRemountSystem) {
                device.remountSystemReadOnly();
            }
            if (mRemountVendor) {
                device.remountVendorReadOnly();
            }
            for (String devicePath : mFilesPushed) {
                device.deleteFile(devicePath);
            }
            // Restore files
            for (Map.Entry<String, String> entry : mBackupFileSpecs.entrySet()) {
                device.executeShellCommand(
                        "mv \"" + entry.getValue() + "\" \"" + entry.getKey() + "\"");
            }
        }
    }

    private void evaluatePushingPair(
            ITestDevice device, IBuildInfo buildInfo, File src, String remotePath)
            throws TargetSetupError, DeviceNotAvailableException {
        String localPath = src.getPath();
        if (!src.isAbsolute()) {
            src = resolveRelativeFilePath(buildInfo, localPath);
        }
        if (src == null || !src.exists()) {
            fail(
                    String.format("Local source file '%s' does not exist", localPath),
                    device.getDeviceDescriptor(),
                    InfraErrorIdentifier.CONFIGURED_ARTIFACT_NOT_FOUND);
            return;
        }
        if (src.isDirectory()) {
            boolean deleteContentOnly = true;
            if (!device.doesFileExist(remotePath)) {
                device.executeShellCommand(String.format("mkdir -p \"%s\"", remotePath));
                deleteContentOnly = false;
            } else if (!device.isDirectory(remotePath)) {
                // File exists and is not a directory
                throw new TargetSetupError(
                        String.format(
                                "Attempting to push dir '%s' to an existing device file '%s'",
                                src.getAbsolutePath(), remotePath),
                        device.getDeviceDescriptor(),
                        DeviceErrorIdentifier.FAIL_PUSH_FILE);
            }
            Set<String> filter = new HashSet<>();
            if (mAbi != null && !mSkipAbiFiltering) {
                String currentArch = AbiUtils.getArchForAbi(mAbi.getName());
                filter.addAll(AbiUtils.getArchSupported());
                filter.remove(currentArch);
            }
            // TODO: Look into using syncFiles but that requires improving sync to work for unroot
            if (!device.pushDir(src, remotePath, filter)) {
                fail(
                        String.format(
                                "Failed to push local '%s' to remote '%s'", localPath, remotePath),
                        device.getDeviceDescriptor(),
                        DeviceErrorIdentifier.FAIL_PUSH_FILE);
                return;
            } else {
                if (deleteContentOnly) {
                    remotePath += "/*";
                }
                mFilesPushed.add(remotePath);
            }
        } else {
            if (!device.pushFile(src, remotePath)) {
                fail(
                        String.format(
                                "Failed to push local '%s' to remote '%s'", localPath, remotePath),
                        device.getDeviceDescriptor(),
                        DeviceErrorIdentifier.FAIL_PUSH_FILE);
                return;
            } else {
                mFilesPushed.add(remotePath);
            }
        }
    }

    @Override
    public Set<String> reportDependencies() {
        Set<String> deps = new HashSet<>();
        try {
            for (File f : getPushSpecs(null).values()) {
                // Match the resolving logic when actually pushing
                if (!f.isAbsolute()) {
                    deps.add(f.getName());
                } else {
                    CLog.d(
                            "%s detected as existing. Not reported as dependency.",
                            f.getAbsolutePath());
                }
            }
        } catch (TargetSetupError e) {
            CLog.e(e);
        }
        return deps;
    }

    public boolean shouldRemountSystem() {
        return mRemountSystem;
    }

    public boolean shouldRemountVendor() {
        return mRemountVendor;
    }

    public boolean isCleanUpEnabled() {
        return mCleanup;
    }
}
