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

import com.nifty.cloud.ncs.NiftyCloudClientException;
import com.nifty.cloud.ncs.NiftyCloudServiceException;
import com.nifty.cloud.ncs.auth.Credentials;
import com.nifty.cloud.ncs.http.ClientProperties;
import com.nifty.cloud.ncs.service.CompleteMultipartUploadResult;
import com.nifty.cloud.ncs.service.PartETag;
import com.nifty.cloud.ncs.service.StorageClient;
import com.nifty.cloud.ncs.service.UploadPartRequest;

/**
 * ニフクラストレージ 　SDK利用 マルチパートアップロードサンプル 
 * 
 */
public class MultipartUploadSample {

	/**
	 * ニフクラストレージ 　SDK利用　マルチパートアップロードサンプル 
	 * @throws IOException 
	 * 
	 */
	public static void main(String[] args) throws IOException {
		
		System.out.println("==========================================================");
		System.out.println("Getting Started with NIFCLOUD Storage Multipart Upload");
		System.out.println("==========================================================\n");
		
		ClientProperties properties = new ClientProperties();
		StorageClient client = new StorageClient(new Credentials(new File("NIFCLOUD_storage.properties")), properties);

		String bucketName = "sample-bucket-name";
		String objectName = "sample-object-name";
		String filePath = "sample-file-path";
		String uploadId = null;

		// マルチアップロードの準備
		File file = new File(filePath);
		if (!file.exists()) {
			System.out.println("File does not exist.");
			System.out.println("File is " + filePath);
			return ;
		}
		long contentLength = file.length();
		long partSize = 5242880;
		System.out.println("ContentLength is " + contentLength);
		System.out.println("Part size is " + partSize + "bytes");

		try {
			// マルチパートアップロードの初期化
			uploadId = client.initiateMultipartUpload(bucketName, objectName);
			System.out.println("Initiate multipart upload " + bucketName + "/" + objectName);
			System.out.println("UploadId is " + uploadId);

			List<PartETag> partETags = new ArrayList<PartETag>();
			
			// パーツをアップロード
			long filePosition = 0;
			
			for (int i = 1; filePosition < contentLength; i++) {
				partSize = Math.min(partSize, (contentLength - filePosition));

				UploadPartRequest uploadRequest = new UploadPartRequest()
						.withBucketName(bucketName).withKey(objectName)
						.withUploadId(uploadId).withPartNumber(i)
						.withFileOffset(filePosition).withFile(file)
						.withPartSize((int)partSize);

				PartETag partETag = client.uploadPart(uploadRequest);
				partETags.add(partETag);
				
				filePosition += partSize;
			}			
			// マルチパートアップロードの完了
			CompleteMultipartUploadResult result = 
				client.completeMultipartUpload(bucketName, objectName, uploadId, partETags);
			System.out.println("Complete multipart upload.");
			System.out.println("Etag is " + result.getETag());
			
		} catch (NiftyCloudServiceException e) {
			System.out.println("Caught NiftyCloudServiceException which means your request made it " +
			"NIFCLOUD Storage, but was rejected with an error response for some reason.");
			System.out.println("Error Message:                " + e.getMessage());
			System.out.println("HTTP Status Code:             " + e.getStatusCode());
			System.out.println("Error Code:                   " + e.getErrorCode());
			System.out.println("Error Type:                   " + e.getErrorType());
			System.out.println("Request ID:                   " + e.getRequestId());
			client.abortMultipartUpload(bucketName, objectName, uploadId);
			System.out.println("Abort multipart upload.");
		} catch (NiftyCloudClientException e) {
            System.out.println("Caught an NiftyCloudClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with NIFCLOUD Storage, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message: " + e.getMessage());
            client.abortMultipartUpload(bucketName, objectName, uploadId);
            System.out.println("Abort multipart upload.");
		}
	}
}
