import io
from sys import version_info
import email
import boto3
from keras.utils.data_utils import get_file as keras_get_file

try:  # python3
    from urllib.request import BaseHandler, URLError, url2pathname, addinfourl
    from urllib.request import build_opener, install_opener

except:  # python2
    from urllib2 import BaseHandler, URLError, url2pathname, addinfourl
    from urllib2 import build_opener, install_opener


def get_file(uri, extract=False):

    if '://' not in uri:
        return uri
        # uri = 'file://' + uri

    fname = uri.split('/')[-1]
    local_path = keras_get_file(
        fname, uri,
        extract=extract,
        cache_subdir='models')

    return local_path


class _FileLikeKey(io.BufferedIOBase):

    def __init__(self, key):
        self.read = key.read


class S3Handler(BaseHandler):

    def s3_open(self, req):
        # The implementation was inspired mainly by the code behind
        # urllib.request.FileHandler.file_open().
        #
        # recipe copied from:
        # http://code.activestate.com/recipes/578957-urllib-handler-for-amazon-s3-buckets/
        # converted to boto3

        if version_info[0] < 3:
            bucket_name = req.get_host()
            key_name = url2pathname(req.get_selector())[1:]
        else:
            bucket_name = req.host
            key_name = url2pathname(req.selector)[1:]

        if not bucket_name or not key_name:
            raise URLError('url must be in the format s3://<bucket>/<key>')

        s3 = boto3.resource('s3')

        key = s3.Object(bucket_name, key_name)

        client = boto3.client('s3')
        obj = client.get_object(Bucket=bucket_name, Key=key_name)
        filelike = _FileLikeKey(obj['Body'])

        origurl = 's3://{}/{}'.format(bucket_name, key_name)

        if key is None:
            raise URLError('no such resource: {}'.format(origurl))

        headers = [
            ('Content-type', key.content_type),
            ('Content-encoding', key.content_encoding),
            ('Content-language', key.content_language),
            ('Content-length', key.content_length),
            ('Etag', key.e_tag),
            ('Last-modified', key.last_modified),
        ]

        headers = email.message_from_string(
            '\n'.join('{}: {}'.format(key, value) for key, value in headers
                      if value is not None))
        return addinfourl(filelike, headers, origurl)


opener = build_opener(S3Handler)
install_opener(opener)