/*
 * Copyright 2010 SpringSource
 *
 * 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 net.anzix.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.ProxyInfoProvider;
import org.apache.maven.wagon.repository.Repository;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
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;
import org.jets3t.service.ServiceException;
import org.jets3t.service.impl.rest.httpclient.GoogleStorageService;
import org.jets3t.service.impl.rest.httpclient.RestStorageService;
import org.jets3t.service.model.StorageObject;
import org.jets3t.service.security.GSCredentials;


/**
 * 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 RestStorageService service;

    private String bucket;

    private String basedir;

    public SimpleStorageServiceWagon() {
        super(false);
    }

    protected void connectToRepository(Repository source, AuthenticationInfo authenticationInfo, ProxyInfoProvider proxyInfoProvider)
            throws AuthenticationException {
        try {
            bucket = source.getHost();
            Credentials c = getCredentials(authenticationInfo);
            service = new GoogleStorageService(new GSCredentials(c.access, c.secret));
        } catch (ServiceException e) {
            throw new AuthenticationException("Cannot authenticate with current credentials", e);
        }
        basedir = getBaseDir(source);
    }

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

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

    protected void getResource(String resourceName, File destination, TransferProgress progress)
            throws ResourceDoesNotExistException, ServiceException, IOException {
        StorageObject object;
        try {
            object = service.getObject(bucket, basedir + resourceName);
        } catch (ServiceException 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 ServiceException {
        StorageObject object = service.getObjectDetails(bucket, basedir + resourceName);
        return object.getLastModifiedDate().compareTo(new Date(timestamp)) < 0;
    }

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

    protected void putResource(File source, String destination, TransferProgress progress) throws ServiceException,
            IOException {
        buildDestinationPath(getDestinationPath(destination));
        StorageObject object = new StorageObject(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 ServiceException {
        StorageObject object = new StorageObject(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.length() > 0 && sb.charAt(sb.length() - 1) != '/') {
            sb.append('/');
        }
        return sb.toString();
    }

    private Credentials getCredentials(AuthenticationInfo authenticationInfo) throws AuthenticationException {
        if (authenticationInfo == null) {
            String example = "<server>\n"
                    + "   <id>repo_key</id>\n"
                    + "   <username>access_key</username>\n"
                    + "   <password>secret_key</password>\n"
                    + "</server>";
            throw new AuthenticationException("Missing authentication info. Add a \n" + example + "\n to your settings.xml!");
        }
        String accessKey = authenticationInfo.getUserName();
        String secretKey = authenticationInfo.getPassphrase();
        if ("".equals(secretKey)) {
            throw new AuthenticationException("With maven3 you should encrypt the secretKey (see http://maven.apache.org/guides/mini/guide-encryption.html) or use the password field.");
        }
        if (secretKey == null) {
            secretKey = authenticationInfo.getPassword();
        }

        if (accessKey == null || secretKey == null) {
            throw new AuthenticationException("S3 requires a username and passphrase to be set.");
        }
        return new Credentials(accessKey, secretKey);
    }

    private class Credentials {

        public String access;

        public String secret;

        public Credentials(String access, String secret) {
            this.access = access;
            this.secret = secret;
        }
    }
}
