import random


class Container(object):

    file_extension_map = {
        'application/octet-stream': '',
        'image/gif': '.gif',
        'image/jpeg': '.jpg',
        'image/png': '.png'
    }

    def __init__(self, name, accepted_content_type):
        self.name = name
        self.accepted_content_type = accepted_content_type

    def get_file_extension(self, content_type):
        if content_type in self.accepted_content_type:
            return self.file_extension_map[content_type]


Container.Binary = Container('binary', ['application/octet-stream'])
Container.Image = Container('image', ['image/gif', 'image/jpeg', 'image/png'])


class RandomStorageKeyGenerator(object):

    leading_letters_in_storage_key = 'abcdefghjkmnpqrstuvwxyz'
    letters_in_storage_key = 'abcdefghjkmnpqrstuvwxyz23456789'

    COMPLEXITY_LIMIT = 16
    complexity = 3

    def next(self):
        if self.complexity > self.COMPLEXITY_LIMIT:
            raise RuntimeError('complexity too high')
        filename = [random.choice(self.leading_letters_in_storage_key)]
        filename += [random.choice(self.letters_in_storage_key) for _ in range(self.complexity)]
        self.complexity += 1
        return ''.join(filename)


class UploadFileResult(object):
    error = None
    storage_string = ''


class WriteFileResult(UploadFileResult):
    pass


class BaseStorage(object):

    def __init__(self, container):
        if not isinstance(container, Container):
            raise TypeError('container must be an instance of Container')
        self.container = container

    def upload_file(self, file_stream, content_type='application/octet-stream', filename=None):
        file_extension = self.container.get_file_extension(content_type)
        if file_extension is None:
            raise ValueError('content type unaccepted')

        result = self.write_file(file_stream, content_type, filename + file_extension)

        return result

    def write_file(self, file_stream, content_type, filename):
        raise NotImplementedError()

    @staticmethod
    def resolve_direct_url(storage_string):
        raise NotImplementedError()
