import boto3
import tempfile

from . import BaseBackend, BaseFile


class S3File(BaseFile):
    def __init__(self, backend, bucket, name, mode):
        self.backend = backend
        self.bucket = bucket
        self.name = name
        self.mode = mode

        self.fp = tempfile.TemporaryFile(mode='b' in mode and 'wb+' or 'w+')

        if 'r' in mode or '+' in mode:
            client = self.backend.get_client()
            client.download_fileobj(self.bucket, self.name, self.fp)

        self.fp.seek(0)

        self.writeback = False

    def close(self):
        if self.writeback:
            self.fp.seek(0)

            client = self.backend.get_client()
            client.upload_fileobj(self.fp, self.bucket, self.name)

        self.fp.close()

    @classmethod
    def open(cls, backend, bucket, name, mode):
        return cls(backend, bucket, name, mode)

    def read(self, size=-1):
        return self.fp.read(size)

    def seek(self, offset, whence=0):
        return self.fp.seek(offset, whence=whence)

    def tell(self):
        return self.fp.tell()

    def write(self, data):
        self.writeback = True
        return self.fp.write(data)


class S3Backend(BaseBackend):
    readable = True
    writeable = True
    seekable = True

    def __init__(self, bucket=None, access_key_id=None, secret_access_key=None, session_token=None):
        self.bucket = bucket
        self.aws_access_key_id = access_key_id,
        self.aws_secret_access_key = secret_access_key,
        self.aws_session_token = session_token,

    def get_client(self):
        return boto3.client('s3',
            aws_access_key_id=self.aws_secret_access_key,
            aws_secret_access_key=self.aws_secret_access_key,
            aws_session_token=self.aws_session_token)

    def open(self, name, mode, bucket=None):
        bucket = bucket or self.bucket
        if not bucket:
            raise ValueError('You must specify a bucket.')
        return S3File(self, bucket, name, mode)

import boto3
import tempfile

from . import BaseBackend, BaseFile


class S3File(BaseFile):
    def __init__(self, backend, bucket, name, mode):
        self.backend = backend
        self.bucket = bucket
        self.name = name
        self.mode = mode

        self.fp = tempfile.TemporaryFile(mode='b' in mode and 'wb+' or 'w+')

        if 'r' in mode or '+' in mode:
            client = self.backend.get_client()
            client.download_fileobj(self.bucket, self.name, self.fp)

        self.fp.seek(0)

        self.writeback = False

    def close(self):
        if self.writeback:
            self.fp.seek(0)

            client = self.backend.get_client()
            client.upload_fileobj(self.fp, self.bucket, self.name)

        self.fp.close()

    @classmethod
    def open(cls, backend, bucket, name, mode):
        return cls(backend, bucket, name, mode)

    def read(self, size=-1):
        return self.fp.read(size)

    def seek(self, offset, whence=0):
        return self.fp.seek(offset, whence=whence)

    def tell(self):
        return self.fp.tell()

    def write(self, data):
        self.writeback = True
        return self.fp.write(data)


class S3Backend(BaseBackend):
    readable = True
    writeable = True
    seekable = True

    def __init__(self, bucket=None, access_key_id=None, secret_access_key=None, session_token=None):
        self.bucket = bucket
        self.aws_access_key_id = access_key_id,
        self.aws_secret_access_key = secret_access_key,
        self.aws_session_token = session_token,

    def get_client(self):
        return boto3.client('s3',
            aws_access_key_id=self.aws_secret_access_key,
            aws_secret_access_key=self.aws_secret_access_key,
            aws_session_token=self.aws_session_token)

    def open(self, name, mode, bucket=None):
        bucket = bucket or self.bucket
        if not bucket:
            raise ValueError('You must specify a bucket.')
        return S3File(self, bucket, name, mode)
