"""
AWS S3 operations
"""
from io import BytesIO
import minio   # https://docs.minio.io/docs/python-client-api-reference
import warnings
import uuid
from pathlib import Path
from . import errors


class Folder:
    """
    A Folder instance manipulates a flat folder of objects within an S3-compatible object store
    """
    def __init__(self, endpoint, bucket, access_key, secret_key, *, secure=False, **_):
        self.client = minio.Minio(endpoint, access_key=access_key, secret_key=secret_key,
                                  secure=secure)
        self.bucket = bucket
        if not self.client.bucket_exists(bucket):
            raise errors.BucketInaccessible('Inaccessible s3 bucket %s' % bucket) from None

    def put(self, name, buffer):
        return self.client.put_object(
            self.bucket, str(name), BytesIO(buffer), length=len(buffer))

    def fput(self, local_file, name, metadata=None):
        return self.client.fput_object(
            self.bucket, str(name), str(local_file), metadata=metadata)

    def get(self, name):
        try:
            return self.client.get_object(self.bucket, str(name)).data
        except minio.error.NoSuchKey:
            raise errors.MissingExternalFile('Missing s3 key %s' % name) from None

    def fget(self, name, local_filepath):
        """get file from object name to local filepath"""
        name = str(name)
        stat = self.client.stat_object(self.bucket, name)
        meta = {k.lower().lstrip('x-amz-meta'): v for k, v in stat.metadata.items()}
        data = self.client.get_object(self.bucket, name)
        local_filepath = Path(local_filepath)
        local_filepath.parent.mkdir(parents=True, exist_ok=True)
        with local_filepath.open('wb') as f:
            for d in data.stream(1 << 16):
                f.write(d)
        if 'contents_hash' in meta:
            return uuid.UUID(meta['contents_hash'])

    def exists(self, name):
        try:
            self.client.stat_object(self.bucket, str(name))
        except minio.error.NoSuchKey:
            return False
        return True

    def get_size(self, name):
        try:
            return self.client.stat_object(self.bucket, str(name)).size
        except minio.error.NoSuchKey:
            raise errors.MissingExternalFile from None

    def remove_object(self, name):
        try:
            self.client.remove_object(self.bucket, str(name))
        except minio.ResponseError:
            return errors.DataJointError('Failed to delete %s from s3 storage' % name)

@@ -142,16 +142,31 @@
 rt uuid%0A
+import logging%0A
 from pat
@@ -204,16 +204,54 @@
 errors%0A%0A
+logger = logging.getLogger(__name__)%0A%0A
 %0Aclass F
@@ -801,16 +801,77 @@
 uffer):%0A
+        logger.debug('put: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         
@@ -1024,24 +1024,104 @@
 data=None):%0A
+        logger.debug('fput: %7B%7D -%3E %7B%7D:%7B%7D'.format(self.bucket, local_file, name))%0A
         retu
@@ -1238,32 +1238,93 @@
 et(self, name):%0A
+        logger.debug('get: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         try:%0A   
@@ -1609,24 +1609,86 @@
 filepath%22%22%22%0A
+        logger.debug('fget: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         name
@@ -2235,32 +2235,96 @@
 ts(self, name):%0A
+        logger.debug('exists: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         try:%0A   
@@ -2486,32 +2486,98 @@
 ze(self, name):%0A
+        logger.debug('get_size: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         try:%0A   
@@ -2731,32 +2731,32 @@
 File from None%0A%0A
-
     def remove_o
@@ -2766,32 +2766,103 @@
 ct(self, name):%0A
+        logger.debug('remove_object: %7B%7D:%7B%7D'.format(self.bucket, name))%0A
         try:%0A   

add logging