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

import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.error.InfraErrorIdentifier;
import com.android.tradefed.targetprep.FlashingResourcesParser;
import com.android.tradefed.targetprep.IFlashingResourcesParser;
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.util.SystemUtil;
import com.android.tradefed.util.ZipUtil;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.PatternFilenameFilter;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * A {@link IBuildProvider} that constructs a {@link IDeviceBuildInfo} based on a provided
 * filesystem directory path.
 * <p/>
 * Specific device build files are recognized based on a configurable set of patterns.
 */
@OptionClass(alias = "local-device-build")
public class LocalDeviceBuildProvider extends StubBuildProvider {

    private static final String BUILD_INFO_FILE = "android-info.txt";
    private static final String BUILD_DIR_OPTION_NAME = "build-dir";

    private String mBootloaderVersion = null;
    private String mRadioVersion = null;

    @Option(name = BUILD_DIR_OPTION_NAME, description = "the directory containing device files.")
    private File mBuildDir = SystemUtil.getProductOutputDir();

    @Option(name = "device-img-pattern", description =
            "the regex use to find device system image zip file within --build-dir.")
    private String mImgPattern = ".*-img-.*\\.zip";

    @Option(name = "test-dir", description = "the directory containing test artifacts.")
    private File mTestDir = null;

    @Option(name = "test-dir-pattern", description =
            "the regex use to find optional test artifact directory within --build-dir. " +
            "Will be ignored if a test-dir is set.")
    private String mTestDirPattern = ".*-tests-.*";

    @Option(name = "bootloader-pattern", description =
            "the regex use to find device bootloader image file within --build-dir.")
    private String mBootloaderPattern = "bootloader.*\\.img";

    @Option(name = "radio-pattern", description =
            "the regex use to find device radio image file within --build-dir.")
    private String mRadioPattern = "radio.*\\.img";

    /**
     * {@inheritDoc}
     */
    @Override
    public IBuildInfo getBuild() throws BuildRetrievalError {
        if (mBuildDir == null) {
            throw new BuildRetrievalError(
                    "Product output directory is not specified. If running "
                            + "from a Android source tree, make sure `lunch` has been run; "
                            + "if outside, provide a valid path via --"
                            + BUILD_DIR_OPTION_NAME,
                    InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
        }
        if (!mBuildDir.exists()) {
            throw new BuildRetrievalError(
                    String.format(
                            "Directory '%s' does not exist. "
                                    + "Please provide a valid path via --%s",
                            mBuildDir.getAbsolutePath(), BUILD_DIR_OPTION_NAME),
                    InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
        }
        if (!mBuildDir.isDirectory()) {
            throw new BuildRetrievalError(
                    String.format(
                            "Path '%s' is not a directory. "
                                    + "Please provide a valid path via --%s",
                            mBuildDir.getAbsolutePath(), BUILD_DIR_OPTION_NAME),
                    InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
        }
        CLog.d("Using device build files from %s", mBuildDir.getAbsolutePath());

        BuildInfo stubBuild = (BuildInfo)super.getBuild();
        DeviceBuildInfo buildInfo = new DeviceBuildInfo(stubBuild.getBuildId(),
                stubBuild.getBuildTargetName());
        buildInfo.addAllBuildAttributes(stubBuild);

        setDeviceImageFile(buildInfo);
        parseBootloaderAndRadioVersions(buildInfo);
        setTestsDir(buildInfo);
        setBootloaderImage(buildInfo);
        setRadioImage(buildInfo);

        return buildInfo;
    }

    /**
     * Parse bootloader and radio versions from the android build info file.
     *
     * @param buildInfo a {@link DeviceBuildInfo}
     * @throws BuildRetrievalError
     */
    void parseBootloaderAndRadioVersions(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
        try {
            IFlashingResourcesParser flashingResourcesParser;
            flashingResourcesParser = new FlashingResourcesParser(
                    buildInfo.getDeviceImageFile());
            mBootloaderVersion = flashingResourcesParser.getRequiredBootloaderVersion();
            mRadioVersion = flashingResourcesParser.getRequiredBasebandVersion();
        } catch (TargetSetupError e) {
            throw new BuildRetrievalError("Unable parse bootloader and radio versions", e);
        }
    }

    /**
     * Find and and set matching device image file to the build.
     *
     * @param buildInfo a {@link DeviceBuildInfo} to set the device image file
     * @throws BuildRetrievalError
     */
    @VisibleForTesting
    void setDeviceImageFile(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
        File deviceImgFile = findFileInDir(mImgPattern);
        if (deviceImgFile == null) {
            CLog.i("Unable to find build image zip on %s", mBuildDir.getAbsolutePath());
            deviceImgFile = createBuildImageZip();
            if (deviceImgFile == null) {
                throw new BuildRetrievalError(
                        String.format(
                                "Could not find device image file matching matching '%s' in '%s'.",
                                mImgPattern, mBuildDir.getAbsolutePath()),
                        InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
            }
        }
        CLog.i("Set build image zip to %s", deviceImgFile.getAbsolutePath());
        buildInfo.setDeviceImageFile(deviceImgFile, buildInfo.getBuildId());
    }

    /**
     * Creates a build image zip file from the given build-dir
     *
     * @return the {@link File} referencing the zip output.
     * @throws BuildRetrievalError
     */
    @VisibleForTesting
    File createBuildImageZip() throws BuildRetrievalError {
        File zipFile = null;
        File[] imageFiles = mBuildDir.listFiles(new PatternFilenameFilter(".*\\.img"));
        File buildInfo = findFileInDir(BUILD_INFO_FILE);
        List<File> buildFiles = new ArrayList<>(Arrays.asList(imageFiles));
        buildFiles.add(buildInfo);
        try {
            zipFile = ZipUtil.createZip(buildFiles);
        } catch (IOException e) {
            throw new BuildRetrievalError("Unable to create build image zip file", e);
        }
        CLog.i("Created build image zip on: %s", zipFile.getAbsolutePath());
        return zipFile;
    }

    void setRadioImage(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
        File radioImgFile = findFileInDir(mRadioPattern);
        if (radioImgFile != null) {
            buildInfo.setBasebandImage(radioImgFile, mRadioVersion);
        }
    }

    void setBootloaderImage(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
        File bootloaderImgFile = findFileInDir(mBootloaderPattern);
        if (bootloaderImgFile != null) {
            buildInfo.setBootloaderImageFile(bootloaderImgFile, mBootloaderVersion);
        }
    }

    /**
     * Find and set a test directory to the build.
     *
     * @param buildInfo a {@link DeviceBuildInfo} to set the test directory
     * @throws BuildRetrievalError
     */
    @VisibleForTesting
    void setTestsDir(DeviceBuildInfo buildInfo) throws BuildRetrievalError {
        File testsDir = null;
        // If test-dir is specified, use it
        if (mTestDir != null) {
            CLog.i("Looking for tests on %s", mTestDir.getAbsolutePath());
            testsDir = mTestDir;
        } else {
            CLog.i("Looking for tests on %s matching %s", mBuildDir.getAbsolutePath(),
                    mTestDirPattern);
            testsDir = findFileInDir(mTestDirPattern);
        }
        if (testsDir != null) {
            buildInfo.setTestsDir(testsDir, buildInfo.getBuildId());
            CLog.d("Using test files from %s", testsDir.getAbsolutePath());
        }
    }

    /**
     * Find a matching file in the build directory.
     *
     * @param regex Regular expression to match a file
     * @return A matching {@link File} or null if none is found
     * @throws BuildRetrievalError
     */
    @VisibleForTesting
    File findFileInDir(String regex) throws BuildRetrievalError {
        return findFileInDir(regex, mBuildDir);
    }

    /**
     * Find a matching file in a given directory.
     *
     * @param regex Regular expression to match a file
     * @param dir a {@link File} referencing the directory to search
     * @return A matching {@link File} or null if none is found
     * @throws BuildRetrievalError
     */
    @VisibleForTesting
    File findFileInDir(String regex, File dir) throws BuildRetrievalError {
        File[] files = dir.listFiles(new PatternFilenameFilter(regex));
        if (files.length == 0) {
            return null;
        } else if (files.length > 1) {
            throw new BuildRetrievalError(
                    String.format(
                            "Found more than one file matching '%s' in '%s'.",
                            regex, mBuildDir.getAbsolutePath()),
                    InfraErrorIdentifier.ARTIFACT_NOT_FOUND);
        }
        return files[0];
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void cleanUp(IBuildInfo info) {
        // ignore
    }

    String getBootloaderVersion() {
        return mBootloaderVersion;
    }

    void setBootloaderVersion(String bootloaderVersion) {
        mBootloaderVersion = bootloaderVersion;
    }

    String getRadioVersion() {
        return mRadioVersion;
    }

    void setRadioVersion(String radioVersion) {
        mRadioVersion = radioVersion;
    }

    File getBuildDir() {
        return mBuildDir;
    }

    void setBuildDir(File buildDir) {
        this.mBuildDir = buildDir;
    }

    /** Returns the directory where the tests are located. */
    public File getTestDir() {
        return mTestDir;
    }

    void setTestDir(File testDir) {
        this.mTestDir = testDir;
    }

    String getTestDirPattern() {
        return mTestDirPattern;
    }

    void setTestDirPattern(String testDirPattern) {
        this.mTestDirPattern = testDirPattern;
    }
}
