/*
 * Copyright 2004-2007 the original author or authors.
 *
 * 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 org.springframework.aws.maven;

import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authentication.AuthenticationInfo;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * An implementation of the Maven Wagon interface that allows you to access the
 * Amazon S3 service. URLs that reference the S3 service should be in the form
 * of <code>s3://bucket.name</code>. As an example
 * <code>s3://static.springframework.org</code> would put files into the
 * <code>static.springframework.org</code> bucket on the S3 service. <p/> This
 * implementation uses the <code>username</code> and <code>passphrase</code>
 * portions of the server authentication metadata for credentials.
 * 
 * @author Ben Hale
 */
public class SimpleStorageServiceWagon extends AbstractWagon {

	private S3Service service;

	private S3Bucket bucket;

	private String basedir;

	public SimpleStorageServiceWagon() {
		super(false);
	}

	protected void connectToRepository(Repository source, AuthenticationInfo authenticationInfo, ProxyInfo proxyInfo)
			throws AuthenticationException {
		try {
			service = new RestS3Service(getCredentials(authenticationInfo));
		}
		catch (S3ServiceException e) {
			throw new AuthenticationException("Cannot authenticate with current credentials", e);
		}
		bucket = new S3Bucket(source.getHost());
		basedir = getBaseDir(source);
	}

	protected boolean doesRemoteResourceExist(String resourceName) {
		try {
			service.getObjectDetails(bucket, basedir + resourceName);
		}
		catch (S3ServiceException e) {
			return false;
		}
		return true;
	}

	protected void disconnectFromRepository() {
		// Nothing to do for S3
	}

	protected void getResource(String resourceName, File destination, TransferProgress progress)
			throws ResourceDoesNotExistException, S3ServiceException, IOException {
		S3Object object;
		try {
			object = service.getObject(bucket, basedir + resourceName);
		}
		catch (S3ServiceException e) {
			throw new ResourceDoesNotExistException("Resource " + resourceName + " does not exist in the repository", e);
		}

		if(!destination.getParentFile().exists()) {
			destination.getParentFile().mkdirs();
		}

		InputStream in = null;
		OutputStream out = null;
		try {
			in = object.getDataInputStream();
			out = new TransferProgressFileOutputStream(destination, progress);
			byte[] buffer = new byte[1024];
			int length;
			while ((length = in.read(buffer)) != -1) {
				out.write(buffer, 0, length);
			}
		}
		finally {
			if (in != null) {
				try {
					in.close();
				}
				catch (IOException e) {
					// Nothing possible at this point
				}
			}
			if (out != null) {
				try {
					out.close();
				}
				catch (IOException e) {
					// Nothing possible at this point
				}
			}
		}
	}

	protected boolean isRemoteResourceNewer(String resourceName, long timestamp) throws S3ServiceException {
		S3Object object = service.getObjectDetails(bucket, basedir + resourceName);
		return object.getLastModifiedDate().compareTo(new Date(timestamp)) < 0;
	}

	protected List<String> listDirectory(String directory) throws Exception {
		S3Object[] objects = service.listObjects(bucket, basedir + directory, "");
		List<String> fileNames = new ArrayList<String>(objects.length);
		for (S3Object object : objects) {
			fileNames.add(object.getKey());
		}
		return fileNames;
	}

	protected void putResource(File source, String destination, TransferProgress progress) throws S3ServiceException,
			IOException {
		buildDestinationPath(getDestinationPath(destination));
		S3Object object = new S3Object(basedir + destination);
		object.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
		object.setDataInputFile(source);
		object.setContentLength(source.length());

		InputStream in = null;
		try {
			service.putObject(bucket, object);

			in = new FileInputStream(source);
			byte[] buffer = new byte[1024];
			int length;
			while ((length = in.read(buffer)) != -1) {
				progress.notify(buffer, length);
			}
		}
		finally {
			if (in != null) {
				try {
					in.close();
				}
				catch (IOException e) {
					// Nothing possible at this point
				}
			}
		}
	}

	private void buildDestinationPath(String destination) throws S3ServiceException {
		S3Object object = new S3Object(basedir + destination + "/");
		object.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
		object.setContentLength(0);
		service.putObject(bucket, object);
		int index = destination.lastIndexOf('/');
		if (index != -1) {
			buildDestinationPath(destination.substring(0, index));
		}
	}

	private String getDestinationPath(String destination) {
		return destination.substring(0, destination.lastIndexOf('/'));
	}

	private String getBaseDir(Repository source) {
		StringBuilder sb = new StringBuilder(source.getBasedir());
		sb.deleteCharAt(0);
		if (sb.charAt(sb.length() - 1) != '/') {
			sb.append('/');
		}
		return sb.toString();
	}

	private AWSCredentials getCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException {
		if (authenticationInfo == null) {
			return null;
		}
		String accessKey = authenticationInfo.getUserName();
		String secretKey = authenticationInfo.getPassphrase();
		if (accessKey == null || secretKey == null) {
			throw new AuthenticationException("S3 requires a username and passphrase to be set");
		}
		return new AWSCredentials(accessKey, secretKey);
	}
}
