package com.qcloud.cos.transfer;

import static com.qcloud.cos.internal.Constants.GB;
import static com.qcloud.cos.internal.Constants.MB;

/**
 * Configuration options for how {@link TransferManager} processes requests.
 * <p>
 * The best configuration settings depend on network configuration, latency and bandwidth. The
 * default configuration settings are suitable for most applications, but this class enables
 * developers to experiment with different configurations and tune transfer manager performance.
 */
public class TransferManagerConfiguration {

    /** Default minimum part size for upload parts. */
    private static final int DEFAULT_MINIMUM_UPLOAD_PART_SIZE = 5 * MB;

    /** Default size threshold for when to use multipart uploads. */
    private static final long DEFAULT_MULTIPART_UPLOAD_THRESHOLD = 5 * MB;

    /** Default size threshold for COS object after which multi-part copy is initiated. */
    private static final long DEFAULT_MULTIPART_COPY_THRESHOLD = 5 * GB;

    /** Default minimum size of each part for multi-part copy. */
    private static final long DEFAULT_MINIMUM_COPY_PART_SIZE = 100 * MB;

    /**
     * The minimum part size for upload parts. Decreasing the minimum part size will cause multipart
     * uploads to be split into a larger number of smaller parts. Setting this value too low can
     * have a negative effect on transfer speeds since it will cause extra latency and network
     * communication for each part.
     */
    private long minimumUploadPartSize = DEFAULT_MINIMUM_UPLOAD_PART_SIZE;

    /**
     * The size threshold, in bytes, for when to use multipart uploads. Uploads over this size will
     * automatically use a multipart upload strategy, while uploads smaller than this threshold will
     * use a single connection to upload the whole object.
     * <p>
     * Multipart uploads are easier to recover from and also potentially faster than single part
     * uploads, especially when the upload parts can be uploaded in parallel as with files. Because
     * there is additional network communication, small uploads are still recommended to use a
     * single connection for the upload.
     */
    private long multipartUploadThreshold = DEFAULT_MULTIPART_UPLOAD_THRESHOLD;

    /**
     * The size threshold, in bytes, for when to use multi-part copy. Copy requests for objects over
     * this size will automatically use a multi-part copy strategy, while copy requests for objects
     * smaller than this threshold will use a single connection to copy the whole object.
     */
    private long multipartCopyThreshold = DEFAULT_MULTIPART_COPY_THRESHOLD;

    /**
     * The minimum size in bytes of each part when a multi-part copy operation is carried out.
     * Decreasing the minimum part size will cause a large number of copy part requests being
     * initiated.
     */
    private long multipartCopyPartSize = DEFAULT_MINIMUM_COPY_PART_SIZE;

    /**
     * Returns the minimum part size for upload parts. Decreasing the minimum part size causes
     * multipart uploads to be split into a larger number of smaller parts. Setting this value too
     * low has a negative effect on transfer speeds, causing extra latency and network communication
     * for each part.
     *
     * @return The minimum part size for upload parts.
     */
    public long getMinimumUploadPartSize() {
        return minimumUploadPartSize;
    }

    /**
     * Sets the minimum part size for upload parts. Decreasing the minimum part size causes
     * multipart uploads to be split into a larger number of smaller parts. Setting this value too
     * low has a negative effect on transfer speeds, causing extra latency and network communication
     * for each part.
     *
     * @param minimumUploadPartSize The minimum part size for upload parts.
     */
    public void setMinimumUploadPartSize(long minimumUploadPartSize) {
        this.minimumUploadPartSize = minimumUploadPartSize;
    }

    /**
     * Returns the size threshold in bytes for when to use multipart uploads. Uploads over this size
     * will automatically use a multipart upload strategy, while uploads smaller than this threshold
     * will use a single connection to upload the whole object.
     * <p>
     * Multipart uploads are easier to recover from and potentially faster than single part uploads,
     * especially when the upload parts can be uploaded in parallel as with files. Due to additional
     * network communication, small uploads should use a single connection for the upload.
     *
     * @return The size threshold in bytes for when to use multipart uploads.
     */
    public long getMultipartUploadThreshold() {
        return multipartUploadThreshold;
    }

    /**
     * Sets the size threshold in bytes for when to use multipart uploads. Uploads over this size
     * will automatically use a multipart upload strategy, while uploads smaller than this threshold
     * will use a single connection to upload the whole object.
     * <p>
     * Multipart uploads are easier to recover from and potentially faster than single part uploads,
     * especially when the upload parts can be uploaded in parallel as with files. Due to additional
     * network communication, small uploads should use a single connection for the upload.
     *
     * @param multipartUploadThreshold The size threshold in bytes for when to use multipart
     *        uploads.
     */
    public void setMultipartUploadThreshold(long multipartUploadThreshold) {
        this.multipartUploadThreshold = multipartUploadThreshold;
    }

    /**
     * Returns the minimum size in bytes of each part in a multi-part copy request. Decreasing this
     * size will result in increase in the number of copy part requests to the server.
     *
     * @return The minimum size in bytes for each part in a multi-part copy request.
     */
    public long getMultipartCopyPartSize() {
        return multipartCopyPartSize;
    }

    /**
     * Sets the minimum part size in bytes for each part in a multi-part copy request. Decreasing
     * this size will result in increase in the number of copy part requests to the server.
     *
     * @param multipartCopyPartSize The minimum size in bytes for each part in a multi part copy
     *        request.
     */
    public void setMultipartCopyPartSize(long multipartCopyPartSize) {
        this.multipartCopyPartSize = multipartCopyPartSize;
    }

    /**
     * Returns the maximum threshold size of an COS object after which the copy operation is carried
     * out using multi-part request.
     *
     * @return The size threshold of an COS object for when to use a multi-part copy
     */
    public long getMultipartCopyThreshold() {
        return multipartCopyThreshold;
    }

    /**
     * Sets the size threshold in bytes for when to use multi-part copy requests. Copy requests for
     * objects over this size will automatically use a multi-part copy strategy, while copy requests
     * for objects smaller than this threshold will use a single connection to copy the whole
     * object.
     *
     * @param multipartCopyThreshold The size threshold in bytes for when to use multi part copy.
     */
    public void setMultipartCopyThreshold(long multipartCopyThreshold) {
        this.multipartCopyThreshold = multipartCopyThreshold;
    }
}
