import aiohttp.web, asyncio, urllib.parse, pathlib, numpy, io, sys, math, os, uvloop, av, PIL.Image, itertools, builtins, huggingface_hub, time, traceback, modelscope

prompts = ['a naked full body front view gorgeous orgasm face slim young cleavage robust boob japanese girl lying on back on white bed, her left hand finger grabing her left nipple, her boobs and cleavage are visible, breast bouncing, her right hand fingers spreading her vagina, spreading legs, buttocks jiggle',
           'her right hand finger grabing her right nipple, her boobs and cleavage are visible, breast bouncing, left hand fingers spreading vagina, spreading legs, buttocks jiggle',
           'camera rapidly zoom in close-up shot to her anus and vagina, she is spreading her labia with her fingers, revealing her pink inner vaginal walls and clitoris',
           'Camera pulls back to reveal her full body',
           'Overhead shot of her full body. The camera rolls in full 360 motion',
           'Camera hitchcock zooms in to her feet', 
           'Camera slowly tilts up to her head']

async def main():
    app = aiohttp.web.Application()
    app.add_routes([aiohttp.web.static('/', pathlib.Path(__file__).resolve().parent, show_index=True)])
    runner = aiohttp.web.AppRunner(app)
    await runner.setup()
    site = aiohttp.web.TCPSite(runner, port=7860)
    await site.start()
    async with aiohttp.ClientSession(headers={'authorization':'Bearer ' + os.getenv('modelscope')}, timeout=aiohttp.ClientTimeout()) as client:
        gorgeous = 'https://chaowenguo-gorgeous.ms.show/'
        async with client.post(urllib.parse.urljoin(gorgeous, 'imageStart'), json={'prompt':'a naked full body front view gorgeous orgasm face slim young cleavage robust boob japanese girl lying on back on white bed, her left hand finger grabing her left nipple, her boobs and cleavage are visible, breast bouncing, her right hand fingers spreading her vagina, spreading legs, buttocks jiggle', 'height':1280, 'width':720}) as _:pass
        while True:
            async with client.get(urllib.parse.urljoin(gorgeous, 'imageGet')) as flux:
                print(flux.status)
                if flux.status == 404: await asyncio.sleep(60)
                else:
                    buffer = io.BytesIO(await flux.content.read())
                    reference = io.BytesIO(buffer.getvalue())
                    image = PIL.Image.open(buffer)
                    image.save('reference.png')
                    with av.open('output.mp4', mode='w') as writer:
                        video = writer.add_stream('h264', rate=8)
                        video.height = image.size[1]
                        video.width = image.size[0]
                        video.pix_fmt = 'yuv420p'
                        audio = writer.add_stream('aac', rate=16000)
                        for prompt, last in itertools.pairwise(prompts):
                            outer = False
                            while True:
                                with aiohttp.MultipartWriter('form-data') as mpwriter:
                                    mpwriter.append(prompt).set_content_disposition('form-data', name='prompt')
                                    mpwriter.append(last).set_content_disposition('form-data', name='last')
                                    mpwriter.append(buffer.getvalue(), {'Content-Type':'image/png'}).set_content_disposition('form-data', name='image', filename='image.png')
                                    mpwriter.append(reference.getvalue(), {'Content-Type':'image/png'}).set_content_disposition('form-data', name='reference', filename='reference.png')
                                    async with client.post(urllib.parse.urljoin(gorgeous, 'videoStart'), data=mpwriter) as _: pass
                                    while True:
                                        try:
                                            async with client.get(urllib.parse.urljoin(gorgeous, 'videoGet')) as get:
                                                print(get.status)
                                                match get.status:
                                                    case 404: await asyncio.sleep(60)
                                                    case 500 | 429: break
                                                    case 200:
                                                        reader = numpy.load(io.BytesIO(await get.content.read())).get('arr_0')
                                                        buffer.seek(0)
                                                        buffer.truncate(0)
                                                        PIL.Image.fromarray(reader[-1]).save(buffer, format='png')
                                                        for frame in itertools.islice(reader, reader.shape[0] - 1): writer.mux(video.encode(av.VideoFrame.from_ndarray(frame)))
                                                        outer = True
                                                        break
                                        except (aiohttp.ClientConnectionError, aiohttp.ClientPayloadError): break
                                    if outer: break
                        writer.mux(video.encode())
                        async with client.post('https://chaowenguo-music.ms.show/get', json={'prompt':'Techno music with a strong, upbeat tempo and high melodic riffs', 'seconds':(builtins.len(prompts) - 1) * 10}) as get:
                            reader = numpy.load(io.BytesIO(await get.content.read())).get('arr_0')
                            for _ in builtins.range(0, reader.shape[0], audio.frame_size):
                                frame = av.AudioFrame.from_ndarray(reader[_:_ + audio.frame_size][None], format='fltp', layout='mono')
                                frame.sample_rate = audio.sample_rate
                                frame.pts = _
                                writer.mux(audio.encode(frame))
                        writer.mux(audio.encode())
                    break
    modelscope.HubApi().upload_file(path_or_fileobj='output.mp4', path_in_repo='gorgeous.mp4', repo_id='chaowenguo/gorgeous', repo_type='dataset', token=os.getenv('modelscope'))
    await asyncio.sleep(math.inf)

try:
    uvloop.run(main())
except:
    pathlib.Path(__file__).resolve().parent.joinpath('gorgeous.txt').write_text(traceback.format_exc())
    huggingface_hub.upload_file(path_or_fileobj='gorgeous.txt', path_in_repo='gorgeous.txt', repo_id='exact-railcar/gorgeous', repo_type='dataset', token=os.getenv('huggingface'))
    time.sleep(math.inf)