/*
 * Copyright (C) 2017 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 android.appsecurity.cts;

import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.IAbi;
import com.android.tradefed.util.AbiUtils;

import junit.framework.TestCase;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

/**
 * Base class for invoking the install-multiple command via ADB. Subclass this for less typing:
 *
 * <code>
 *     private class InstallMultiple extends BaseInstallMultiple&lt;InstallMultiple&gt; {
 *         public InstallMultiple() {
 *             super(getDevice(), null, null);
 *         }
 *     }
 * </code>
 */
public class BaseInstallMultiple<T extends BaseInstallMultiple<?>> {
    private final ITestDevice mDevice;
    private final IBuildInfo mBuild;
    private final IAbi mAbi;

    static class DeviceFile {
        public final File localFile;
        public final File remoteFile;
        public final boolean addToInstallSession;
        public final boolean manageRemoteFile;

        private DeviceFile(File localFile, File remoteFile, boolean addToInstallSession,
                boolean manageRemoteFile) {
            this.localFile = localFile;
            this.remoteFile = remoteFile;
            this.addToInstallSession = addToInstallSession;
            this.manageRemoteFile = manageRemoteFile;
        }

        static DeviceFile addToSession(File file) {
            return new DeviceFile(file, file, true, true);
        }

        static DeviceFile renameAndAddToSession(File localFile, File remoteFile) {
            return new DeviceFile(localFile, remoteFile, true, true);
        }

        static DeviceFile pushOnly(File file) {
            return new DeviceFile(file, file, false, true);
        }

        static DeviceFile renameAndPushOnly(File localFile, File remoteFile) {
            return new DeviceFile(localFile, remoteFile, false, true);
        }

        static DeviceFile addRemoteFileToSession(File remoteFile) {
            return new DeviceFile(null, remoteFile, true, false);
        }
    }

    private final List<String> mArgs = new ArrayList<>();
    private final List<DeviceFile> mFilesToAdd = new ArrayList<>();
    private final List<String> mSplitsToRemove = new ArrayList<>();
    private boolean mUseNaturalAbi = false;
    private boolean mUseIncremental = false;

    public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi) {
        this(device, buildInfo, abi, true);
    }

    public BaseInstallMultiple(ITestDevice device, IBuildInfo buildInfo, IAbi abi,
            boolean grantPermissions) {
        mDevice = device;
        mBuild = buildInfo;
        mAbi = abi;
        if (grantPermissions) {
            addArg("-g");
        }
        // Allow the install of test apps
        addArg("-t");
    }

    T addArg(String arg) {
        mArgs.add(arg);
        return (T) this;
    }

    T addFile(String file) throws FileNotFoundException {
        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
        mFilesToAdd.add(DeviceFile.addToSession(buildHelper.getTestFile(file, mAbi)));
        return (T) this;
    }

    T addRemoteFile(String remoteFile) {
        mFilesToAdd.add(DeviceFile.addRemoteFileToSession(new File(remoteFile)));
        return (T) this;
    }

    T renameAndAddFile(String localFile, String remoteFile) throws FileNotFoundException {
        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
        mFilesToAdd.add(DeviceFile.renameAndAddToSession(buildHelper.getTestFile(localFile, mAbi),
                buildHelper.getTestFile(remoteFile, mAbi)));
        return (T) this;
    }

    T pushFile(String file) throws FileNotFoundException {
        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
        mFilesToAdd.add(DeviceFile.pushOnly(buildHelper.getTestFile(file, mAbi)));
        return (T) this;
    }

    T renameAndPushFile(String localFile, String remoteFile) throws FileNotFoundException {
        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
        mFilesToAdd.add(DeviceFile.renameAndPushOnly(buildHelper.getTestFile(localFile, mAbi),
                buildHelper.getTestFile(remoteFile, mAbi)));
        return (T) this;
    }

    T removeSplit(String split) {
        mSplitsToRemove.add(split);
        return (T) this;
    }

    T inheritFrom(String packageName) {
        addArg("-r");
        addArg("-p " + packageName);
        return (T) this;
    }

    T useNaturalAbi() {
        mUseNaturalAbi = true;
        return (T) this;
    }

    T useIncremental() {
        mUseIncremental = true;
        return (T) this;
    }

    T allowTest() {
        addArg("-t");
        return (T) this;
    }

    T locationAuto() {
        addArg("--install-location 0");
        return (T) this;
    }

    T locationInternalOnly() {
        addArg("--install-location 1");
        return (T) this;
    }

    T locationPreferExternal() {
        addArg("--install-location 2");
        return (T) this;
    }

    T forceUuid(String uuid) {
        addArg("--force-uuid " + uuid);
        return (T) this;
    }

    T forUser(int userId) {
        addArg("--user " + userId);
        return (T) this;
    }

    T restrictPermissions() {
        addArg("--restrict-permissions");
        return (T) this;
    }

    T forceQueryable() {
        addArg("--force-queryable");
        return (T) this;
    }

    protected String deriveRemoteName(String originalName, int index) {
        return index + "_" + originalName;
    }

    void run() throws DeviceNotAvailableException {
        run(true, null);
    }

    void run(boolean expectingSuccess) throws DeviceNotAvailableException {
        run(expectingSuccess, null);
    }

    void runExpectingFailure() throws DeviceNotAvailableException {
        run(false, null);
    }

    void runExpectingFailure(String failure) throws DeviceNotAvailableException {
        run(false, failure);
    }

    private void run(boolean expectingSuccess, String failure) throws DeviceNotAvailableException {
        if (mUseIncremental) {
            runIncremental(expectingSuccess, failure);
        } else {
            runNonIncremental(expectingSuccess, failure);
        }
        cleanupDeviceFiles();
    }

    String runForResult() throws DeviceNotAvailableException {
        String result;
        if (mUseIncremental) {
            result = runIncrementalForResult();
        } else {
            result = runNonIncrementalForResult();
        }
        cleanupDeviceFiles();
        return result;
    }

    private String runNonIncrementalForResult() throws DeviceNotAvailableException {
        final ITestDevice device = mDevice;

        // Create an install session
        final StringBuilder cmd = new StringBuilder();
        cmd.append("pm install-create");
        for (String arg : mArgs) {
            cmd.append(' ').append(arg);
        }
        if (!mUseNaturalAbi && mAbi != null) {
            cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
        }

        String result = device.executeShellCommand(cmd.toString());
        TestCase.assertTrue(result, result.startsWith("Success"));

        final int start = result.lastIndexOf("[");
        final int end = result.lastIndexOf("]");
        int sessionId = -1;
        try {
            if (start != -1 && end != -1 && start < end) {
                sessionId = Integer.parseInt(result.substring(start + 1, end));
            }
        } catch (NumberFormatException e) {
        }
        if (sessionId == -1) {
            throw new IllegalStateException("Failed to create install session: " + result);
        }

        // Push our files into session. Ideally we'd use stdin streaming,
        // but ddmlib doesn't support it yet.
        for (int i = 0; i < mFilesToAdd.size(); i++) {
            boolean manageRemoteFile = mFilesToAdd.get(i).manageRemoteFile;
            final File localFile = mFilesToAdd.get(i).localFile;
            final File remoteFile = mFilesToAdd.get(i).remoteFile;
            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
            final String remotePath = "/data/local/tmp/" + remoteName;
            if (manageRemoteFile && !device.pushFile(localFile, remotePath)) {
                throw new IllegalStateException("Failed to push " + localFile);
            }

            if (!mFilesToAdd.get(i).addToInstallSession) {
                continue;
            }

            cmd.setLength(0);
            cmd.append("pm install-write");
            cmd.append(' ').append(sessionId);
            cmd.append(' ').append(remoteName);
            cmd.append(' ').append(remotePath);

            result = device.executeShellCommand(cmd.toString());
            TestCase.assertTrue(result, result.startsWith("Success"));
        }

        for (int i = 0; i < mSplitsToRemove.size(); i++) {
            final String split = mSplitsToRemove.get(i);

            cmd.setLength(0);
            cmd.append("pm install-remove");
            cmd.append(' ').append(sessionId);
            cmd.append(' ').append(split);

            result = device.executeShellCommand(cmd.toString());
            TestCase.assertTrue(result, result.startsWith("Success"));
        }

        // Everything staged; let's pull trigger
        cmd.setLength(0);
        cmd.append("pm install-commit");
        cmd.append(' ').append(sessionId);

        return device.executeShellCommand(cmd.toString()).trim();
    }

    private void runNonIncremental(boolean expectingSuccess, String failure)
            throws DeviceNotAvailableException {
        String result = runNonIncrementalForResult();
        if (failure == null) {
            if (expectingSuccess) {
                TestCase.assertTrue(result, result.startsWith("Success"));
            } else {
                TestCase.assertFalse(result, result.startsWith("Success"));
            }
        } else {
            TestCase.assertTrue(result, result.contains(failure));
        }
    }

    private String runIncrementalForResult() throws DeviceNotAvailableException {
        final ITestDevice device = mDevice;

        if (!mSplitsToRemove.isEmpty()) {
            throw new IllegalStateException("Incremental sessions can't remove splits");
        }

        // Create an install session
        final StringBuilder cmd = new StringBuilder();
        cmd.append("pm install-incremental");
        for (String arg : mArgs) {
            cmd.append(' ').append(arg);
        }
        if (!mUseNaturalAbi && mAbi != null) {
            cmd.append(' ').append(AbiUtils.createAbiFlag(mAbi.getName()));
        }

        // Push our files into session. Ideally we'd use stdin streaming,
        // but ddmlib doesn't support it yet.
        for (int i = 0; i < mFilesToAdd.size(); i++) {
            boolean manageRemoteFile = mFilesToAdd.get(i).manageRemoteFile;
            final File localFile = mFilesToAdd.get(i).localFile;
            final File remoteFile = mFilesToAdd.get(i).remoteFile;
            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
            final String remotePath = "/data/local/tmp/" + remoteName;
            if (manageRemoteFile && !device.pushFile(localFile, remotePath)) {
                throw new IllegalStateException("Failed to push " + localFile);
            }

            if (!mFilesToAdd.get(i).addToInstallSession) {
                continue;
            }

            cmd.append(' ').append(remotePath);
        }

        // Everything staged; let's pull trigger
        return device.executeShellCommand(cmd.toString()).trim();
    }

    private void runIncremental(boolean expectingSuccess, String failure)
            throws DeviceNotAvailableException {
        String result = runIncrementalForResult();
        if (failure == null) {
            if (expectingSuccess) {
                TestCase.assertTrue(result, result.startsWith("Success"));
            } else {
                TestCase.assertFalse(result, result.startsWith("Success"));
            }
        } else {
            TestCase.assertTrue(result, result.contains(failure));
        }
    }

    private void cleanupDeviceFiles() throws DeviceNotAvailableException {
        final ITestDevice device = mDevice;
        for (int i = 0; i < mFilesToAdd.size(); i++) {
            if (!mFilesToAdd.get(i).manageRemoteFile) {
                continue;
            }
            final File remoteFile = mFilesToAdd.get(i).remoteFile;
            final String remoteName = deriveRemoteName(remoteFile.getName(), i);
            final String remotePath = "/data/local/tmp/" + remoteName;
            device.deleteFile(remotePath);
        }
    }
}
