#!/usr/bin/env python3

import asyncio
import io
import os.path
from concurrent.futures import ProcessPoolExecutor
from urllib.parse import urlparse

import aiofiles

try:
    import PIL.Image
except ImportError:
    PIL = None

try:
    from . import peony, api
except (SystemError, ImportError):
    from __init__ import peony, utils
    import api

client = peony.PeonyClient(**api.keys)


def convert(img, formats):
    """
        Convert the image to all the formats specified
    Parameters
    ----------
    img : PIL.Image.Image
        The image to convert
    formats : list
        List of all the formats to use
    Returns
    -------
    io.BytesIO
        A file object containing the converted image
    """
    media = None
    min_size = 0

    for kwargs in formats:
        f = io.BytesIO()
        img.save(f, **kwargs)
        size = f.tell()

        if media is None or size < min_size:
            if media is not None:
                media.close()

            media = f
            min_size = size
        else:
            f.close()

    return media


def optimize_media(file_, max_size, formats):
    """
        Optimize an image
    Resize the picture to the ``max_size``, defaulting to the large
    photo size of Twitter in :meth:`PeonyClient.upload_media` when
    used with the ``optimize_media`` argument.
    Parameters
    ----------
    file_ : file object
        the file object of an image
    max_size : :obj:`tuple` or :obj:`list` of :obj:`int`
        a tuple in the format (width, height) which is maximum size of
        the picture returned by this function
    formats : :obj`list` or :obj:`tuple` of :obj:`dict`
        a list of all the formats to convert the picture to
    Returns
    -------
    file
        The smallest file created in this function
    """
    if not PIL:
        msg = ("Pillow must be installed to optimize a media\n"
               "(pip3 install peony[Pillow])")
        raise RuntimeError(msg)

    img = PIL.Image.open(file_)

    # resize the picture (defaults to the 'large' photo size of Twitter
    # in peony.PeonyClient.upload_media)
    ratio = max(hw / max_hw for hw, max_hw in zip(img.size, max_size))

    if ratio > 1:
        size = tuple(int(hw // ratio) for hw in img.size)
        img = img.resize(size, PIL.Image.ANTIALIAS)

    media = convert(img, formats)

    # do not close a file opened by the user
    # only close if a filename was given
    if not hasattr(file_, 'read'):
        img.close()

    return media


async def process_media(media, path):
    mime_type = await utils.get_type(media, path)
    if not mime_type.startswith('image'):
        return media

    # formats to try when converting the picture
    formats = [dict(format='PNG'),
               dict(format='JPEG', quality=90, optimize=True)]

    # PIL can't read an aiofiles file
    file = io.BytesIO(await media.read())

    return await client.loop.run_in_executor(
        ProcessPoolExecutor(),
        optimize_media,
        file,
        (2048, 2048),
        formats
    )


async def send_tweet_with_media():
    # read the tweet's status
    status = input("status: ")

    path = ""
    while not path and not os.path.exists(path):
        path = input('file to upload:\n')

    # read the most common input formats
    path = urlparse(path).path.strip(" \"'")

    async with aiofiles.open(path, 'rb') as media:
        # optimize pictures if PIL is available
        if PIL:
            media = await process_media(media, path)

        uploaded = await client.upload_media(media,
                                             chunk_size=2**18,
                                             chunked=True)
        media_id = uploaded.media_id
        await client.api.statuses.update.post(status=status,
                                              media_ids=media_id)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(send_tweet_with_media())

@@ -806,16 +806,328 @@
 tesIO()%0A
+        if img.mode == %22RGBA%22 and kwargs%5B'format'%5D != %22PNG%22:%0A            # convert to RGB if picture is too large as a png%0A            # this implies that the png format is the first in %60formats%60%0A            if min_size %3C 5*1024**2:%0A                continue%0A            else:%0A                img.convert('RGB')%0A%0A
         
@@ -1148,16 +1148,16 @@
 kwargs)%0A
-
         
@@ -2219,17 +2219,18 @@
        %22
-(
+$ 
 pip3 ins
@@ -2238,22 +2238,14 @@
 all 
-peony%5B
 Pillow
-%5D)
 %22)%0A 
@@ -2853,24 +2853,54 @@
 dia, path):%0A
+    data = await media.read()%0A
     mime_typ
@@ -2924,20 +2924,19 @@
 et_type(
-medi
+dat
 a, path)
@@ -3152,89 +3152,8 @@
 )%5D%0A%0A
-    # PIL can't read an aiofiles file%0A    file = io.BytesIO(await media.read())%0A%0A
     
@@ -3257,20 +3257,32 @@
         
-file
+io.BytesIO(data)
 ,%0A      

update the upload example