package org.getopentest.actions.s3;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.getopentest.base.TestAction;

/**
 * Read the contents of an object from an AWS S3 bucket into a file on disk.
 */
public class GetS3Object extends TestAction {

    @Override
    public void run() {
        super.run();

        String awsCredentialsProfile = this.readStringArgument("awsProfile", "default");
        String bucket = this.readStringArgument("bucket");
        String objectKey = this.readStringArgument("objectKey");
        String targetFilePath = this.readStringArgument("targetFile");
        Boolean overwrite = this.readBooleanArgument("overwrite", false);

        AmazonS3 s3Client = new AmazonS3Client(new ProfileCredentialsProvider(awsCredentialsProfile));
        S3Object object = s3Client.getObject(
                new GetObjectRequest(bucket, objectKey));
        InputStream objectDataStream = object.getObjectContent();

        if (targetFilePath != null) {
            File targetFile = new File(targetFilePath);
            if (!targetFile.isAbsolute()) {
                targetFile = Paths.get(this.getActor().getTempDir().getAbsolutePath(), targetFilePath).toFile();
            }
            targetFile.getParentFile().mkdirs();

            try {
                if (overwrite) {
                    Files.copy(objectDataStream, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                } else {
                    Files.copy(objectDataStream, targetFile.toPath());
                }
            } catch (Exception ex) {
                throw new RuntimeException(String.format(
                        "Failed to transfer data from the input stream into file %s",
                        targetFilePath), ex);
            }
            
            this.writeArgument("targetFile", targetFile.getAbsolutePath());
        } else {
            // TODO: Make targetFile arg optional so this branch can execute.
            // Read data in memory and write it to an output value
        }
    }
}