package com.zakgof.db.velvet.dynamodb;

import java.net.URI;
import java.util.Map;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.google.common.base.Splitter;
import com.zakgof.db.txn.ITransactionCall;
import com.zakgof.db.velvet.IVelvet;
import com.zakgof.db.velvet.VelvetException;
import com.zakgof.db.velvet.impl.AVelvetEnvironment;

public class DynamoDBVelvetEnv extends AVelvetEnvironment {

    private final DynamoDB db;

    public DynamoDBVelvetEnv(URI uri) {
        String region = uri.getPath().replaceAll("/", "");
        String query = uri.getQuery();
        final Map<String, String> params = Splitter.on('&').trimResults().withKeyValueSeparator("=").split(query);

        String awsAccessKeyId = params.get("awsAccessKeyId");
        String awsSecretKey = params.get("awsSecretKey");

        ClientConfiguration clientConfig = new ClientConfiguration();
        String proxyHost = params.get("proxyHost");
        if (proxyHost != null) {
            String proxyPort = params.getOrDefault("proxyPort", "80");
            int port = proxyPort.matches("\\d+") ? Integer.parseInt(proxyPort) : 80;

            clientConfig.withProxyHost(proxyHost).withProxyPort(port);
            String proxyUser = params.get("proxyUser");
            if (proxyUser != null) {
                clientConfig.withProxyUsername(proxyUser);
            }
            String proxyPassword = params.get("proxyPassword");
            if (proxyPassword != null) {
                clientConfig.withProxyPassword(proxyPassword);
            }
        }
        clientConfig.withMaxErrorRetry(24);

        AmazonDynamoDB dynamodb = AmazonDynamoDBClientBuilder
           .standard()
           .withRegion(region)
           .withCredentials(new AWSStaticCredentialsProvider(new AWSCredentials() {
                @Override
                public String getAWSAccessKeyId() {
                    return awsAccessKeyId;
                }

                @Override
                public String getAWSSecretKey() {
                    return awsSecretKey;
                }
            }))
           .withClientConfiguration(clientConfig)
           .build();

        db = new DynamoDB(dynamodb);
    }

    @Override
    public void execute(ITransactionCall<IVelvet> transaction) {
        try {
            transaction.execute(new DynamoDBVelvet(db, this::instantiateSerializer));
        } catch (Throwable e) {
            if (e instanceof RuntimeException)
                throw (RuntimeException)e;
            else if (e instanceof Error)
                throw (Error)e;
            throw new VelvetException(e);
        }
    }

    @Override
    public void close() {
        db.shutdown();
    }
}

@@ -148,16 +148,22 @@
 auth.AWS
+Static
 Credenti
@@ -165,16 +165,24 @@
 dentials
+Provider
 ;%0Aimport
@@ -197,33 +197,32 @@
 zonaws.auth.
-AWSStatic
+BasicAWS
 CredentialsP
@@ -216,32 +216,24 @@
 SCredentials
-Provider
 ;%0Aimport com
@@ -1908,17 +1908,29 @@
 moDB
- dynamodb
+ClientBuilder builder
  = A
@@ -1955,16 +1955,27 @@
 tBuilder
+.standard()
 %0A       
@@ -1979,25 +1979,52 @@
        .
-standard(
+withClientConfiguration(clientConfig
 )%0A      
@@ -2043,24 +2043,26 @@
 gion(region)
+;%0A
 %0A           
@@ -2054,27 +2054,83 @@
 );%0A%0A        
-   
+if (awsAccessKeyId != null) %7B%0A            builder = builder
 .withCredent
@@ -2171,16 +2171,21 @@
 der(new 
+Basic
 AWSCrede
@@ -2195,410 +2195,297 @@
 als(
-) %7B%0A                @Override%0A                public String getAWSAccessKeyId() %7B%0A                    return awsAccessKeyId;%0A                %7D%0A%0A                @Override%0A                public String getAWSSecretKey() %7B%0A                    return awsSecretKey;%0A                %7D%0A            %7D))%0A           .withClientConfiguration(clientConfig)%0A           .build();%0A%0A        db = new DynamoDB(dynamodb)
+awsAccessKeyId, awsSecretKey)));%0A        %7D%0A%0A        this.db = new DynamoDB(builder.build());%0A    %7D%0A%0A    public DynamoDBVelvetEnv(AmazonDynamoDB amazonDynamoDB) %7B%0A        this(new DynamoDB(amazonDynamoDB));%0A    %7D%0A%0A    public DynamoDBVelvetEnv(DynamoDB dynamoDB) %7B%0A        this.db = dynamoDB
 ;%0A  

Allow connect to Dynamo without explicit credentials