/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.jackrabbit.oak.blob.cloud.s3;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.util.StringUtils;
import com.google.common.collect.Maps;

/**
 * Amazon S3 utilities.
 */
public final class Utils {

    private static final Logger LOG = LoggerFactory.getLogger(Utils.class);

    public static final String DEFAULT_CONFIG_FILE = "aws.properties";

    private static final String DELETE_CONFIG_SUFFIX = ";burn";

    /**
     * The default value AWS bucket region.
     */
    public static final String DEFAULT_AWS_BUCKET_REGION = "us-standard";

    /**
     * The value for the us-east-1 region.
     */
    public static final String US_EAST_1_AWS_BUCKET_REGION = "us-east-1";

    /**
     * constants to define endpoint to various AWS region
     */
    public static final String AWSDOTCOM = "amazonaws.com";

    public static final String S3 = "s3";

    public static final String DOT = ".";

    public static final String DASH = "-";

    /**
     * private constructor so that class cannot initialized from outside.
     */
    private Utils() {

    }

    /**
     * Create AmazonS3Client from properties.
     * 
     * @param prop properties to configure @link {@link AmazonS3Client}
     * @return {@link AmazonS3Client}
     */
    public static AmazonS3Client openService(final Properties prop) {
        String accessKey = prop.getProperty(S3Constants.ACCESS_KEY);
        String secretKey = prop.getProperty(S3Constants.SECRET_KEY);
        AmazonS3Client s3service = null;
        if (StringUtils.isNullOrEmpty(accessKey)
                || StringUtils.isNullOrEmpty(secretKey)) {
            LOG.info("Configuring Amazon Client from environment");
            s3service = new AmazonS3Client(getClientConfiguration(prop));
        } else {
            LOG.info("Configuring Amazon Client from property file.");
            AWSCredentials credentials = new BasicAWSCredentials(accessKey,
                    secretKey);
            s3service = new AmazonS3Client(credentials,
                    getClientConfiguration(prop));
        }
        String region = prop.getProperty(S3Constants.S3_REGION);
        String endpoint = null;
        String propEndPoint = prop.getProperty(S3Constants.S3_END_POINT);
        if ((propEndPoint != null) & !"".equals(propEndPoint)) {
            endpoint = propEndPoint;
        } else {
            if (StringUtils.isNullOrEmpty(region)) {
                com.amazonaws.regions.Region s3Region = Regions.getCurrentRegion();
                if (s3Region != null) {
                    region = s3Region.getName();
                } else {
                    throw new AmazonClientException(
                            "parameter ["
                                    + S3Constants.S3_REGION
                                    + "] not configured and cannot be derived from environment");
                }
            }
            if (DEFAULT_AWS_BUCKET_REGION.equals(region)) {
                endpoint = S3 + DOT + AWSDOTCOM;
            } else {
                endpoint = S3 + DOT + region + DOT + AWSDOTCOM;
            }
        }
        /*
         * setting endpoint to remove latency of redirection. If endpoint is
         * not set, invocation first goes us standard region, which
         * redirects it to correct location.
         */
        s3service.setEndpoint(endpoint);
        LOG.info("S3 service endpoint [{}] ", endpoint);
        return s3service;
    }

    /**
     * Waits for an S3 bucket, one we expect to exist, to report that it exists.
     * A check for the bucket is called with a limited number of repeats with
     * an increasing backoff.
     *
     * Usually you would call this after creating a bucket to block until the
     * bucket is actually available before moving forward with other tasks that
     * expect the bucket to be available.
     *
     * @param s3Client The AmazonS3 client connection to the storage service.
     * @param bucketName The name of the bucket to check.
     * @return True if the bucket exists; false otherwise.
     */
    public static boolean waitForBucket(@NotNull final AmazonS3 s3Client, @NotNull final String bucketName) {
        int tries = 0;
        boolean bucketExists = false;
        while (20 > tries++) {
            bucketExists = s3Client.doesBucketExistV2(bucketName);
            if (bucketExists) break;
            try {
                Thread.sleep(100 * tries);
            }
            catch (InterruptedException e) { }
        }
        return bucketExists;
    }

    /**
     * Delete S3 bucket. This method first deletes all objects from bucket and
     * then delete empty bucket.
     * 
     * @param bucketName the bucket name.
     */
    public static void deleteBucket(final String bucketName) throws IOException {
        Properties prop = readConfig(DEFAULT_CONFIG_FILE);
        AmazonS3 s3service = openService(prop);
        ObjectListing prevObjectListing = s3service.listObjects(bucketName);
        while (true) {
            for (S3ObjectSummary s3ObjSumm : prevObjectListing.getObjectSummaries()) {
                s3service.deleteObject(bucketName, s3ObjSumm.getKey());
            }
            if (!prevObjectListing.isTruncated()) {
                break;
            }
            prevObjectListing = s3service.listNextBatchOfObjects(prevObjectListing);
        }
        s3service.deleteBucket(bucketName);
    }

    /**
     * Read a configuration properties file. If the file name ends with ";burn",
     * the file is deleted after reading.
     * 
     * @param fileName the properties file name
     * @return the properties
     * @throws java.io.IOException if the file doesn't exist
     */
    public static Properties readConfig(String fileName) throws IOException {
        boolean delete = false;
        if (fileName.endsWith(DELETE_CONFIG_SUFFIX)) {
            delete = true;
            fileName = fileName.substring(0, fileName.length()
                - DELETE_CONFIG_SUFFIX.length());
        }
        if (!new File(fileName).exists()) {
            throw new IOException("Config file not found: " + fileName);
        }
        Properties prop = new Properties();
        InputStream in = null;
        try {
            in = new FileInputStream(fileName);
            prop.load(in);
        } finally {
            if (in != null) {
                in.close();
            }
            if (delete) {
                deleteIfPossible(new File(fileName));
            }
        }
        return prop;
    }

    private static void deleteIfPossible(final File file) {
        boolean deleted = file.delete();
        if (!deleted) {
            LOG.warn("Could not delete " + file.getAbsolutePath());
        }
    }

    private static ClientConfiguration getClientConfiguration(Properties prop) {
        int connectionTimeOut = Integer.parseInt(prop.getProperty(S3Constants.S3_CONN_TIMEOUT));
        int socketTimeOut = Integer.parseInt(prop.getProperty(S3Constants.S3_SOCK_TIMEOUT));
        int maxConnections = Integer.parseInt(prop.getProperty(S3Constants.S3_MAX_CONNS));
        int maxErrorRetry = Integer.parseInt(prop.getProperty(S3Constants.S3_MAX_ERR_RETRY));
        String encryptionType = prop.getProperty(S3Constants.S3_ENCRYPTION);

        String protocol = prop.getProperty(S3Constants.S3_CONN_PROTOCOL);
        String proxyHost = prop.getProperty(S3Constants.PROXY_HOST);
        String proxyPort = prop.getProperty(S3Constants.PROXY_PORT);

        ClientConfiguration cc = new ClientConfiguration();

        if (protocol != null && protocol.equalsIgnoreCase("http")) {
            cc.setProtocol(Protocol.HTTP);
        }

        if (proxyHost != null && !proxyHost.isEmpty()) {
            cc.setProxyHost(proxyHost);
        }

        if (proxyPort != null && !proxyPort.isEmpty()) {
            cc.setProxyPort(Integer.parseInt(proxyPort));
        }

        cc.setConnectionTimeout(connectionTimeOut);
        cc.setSocketTimeout(socketTimeOut);
        cc.setMaxConnections(maxConnections);
        cc.setMaxErrorRetry(maxErrorRetry);
        if (encryptionType != null
                && encryptionType.equals(S3Constants.S3_ENCRYPTION_SSE_KMS)) {
            cc.withSignerOverride("AWSS3V4SignerType");
        }
        return cc;
    }

    public static Map<String, Object> asMap(Properties props) {
        Map<String, Object> map = Maps.newHashMap();
        for (Object key : props.keySet()) {
            map.put((String)key, props.get(key));
        }
        return map;
    }
}
