from __main__ import app

from PIL import Image, ImageOps
from flask import request
import requests
import validators
import logging
import io

from utils import flask_utils


sprite_size = 112
sprites = 5
allowed_content_length = 4_000_000
allowed_image_formats = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']


@app.route('/memes/pat/file.gif')  # to directly embed, discord _requires_ this file ending, it seems
def pat_animated():
    url = request.args.get('url')
    if not validators.url(url):
        return 'no valid url', 400
    session = requests.Session()
    response = session.head(url)
    content_type = response.headers['content-type']

    if content_type not in allowed_image_formats:
        return f'Incorrect image type {content_type}', 400

    actual_content_length = int(response.headers['content-length'])
    if actual_content_length > allowed_content_length:
        return f'Image too large {actual_content_length}', 400

    image_file = requests.get(url, stream=True)
    input_image = Image.open(io.BytesIO(image_file.content))
    original_input_image = input_image
    frame_count = original_input_image.n_frames
    old_width, old_height = input_image.size
    with Image.open('resources/img/pat_sprite.png') as pat_background:
        pat_background = pat_background.convert('RGBA')
        pat_width, pat_height = pat_background.size
        pat_ratio = old_width / sprite_size
        original_background_images = []
        for i in range(sprites):
            background_part = pat_background.crop((i * sprite_size, 0, (i + 1) * sprite_size, pat_height))
            original_background_images.append(background_part)
        desired_new_pat_width = int(sprite_size * pat_ratio)
        resized_background_images = []
        for background_image in original_background_images:
            if pat_ratio > 1:
                resized_background = background_image.resize((desired_new_pat_width, pat_height))
            else:
                resized_background = ImageOps.contain(background_image, (desired_new_pat_width, pat_height))
            resized_background_images.append(resized_background)
        if content_type == 'image/gif':
            logging.info(f'Rendering pat for gif.')
            old_frames = []
            for frame_index in range(frame_count):
                input_image.seek(frame_index)
                frame = input_image.convert('RGBA')
                old_frames.append(frame)
            frames = []
            for index, old_frame in enumerate(old_frames):
                frame = Image.new('RGBA', (old_width, old_height), (0, 0, 0, 0))
                frame.paste(old_frame, (0, 0), old_frame)
                frame_background_image = resized_background_images[index % sprites]
                frame.paste(frame_background_image, (0, 0), frame_background_image)
                frames.append(frame)
            return flask_utils.serve_pil_gif_image(frames, int(original_input_image.info['duration']))
        else:
            frames = []
            logging.info(f'Rendering pat for static image.')
            input_image = input_image.convert('RGBA')
            for background_image in resized_background_images:
                frame = Image.new('RGBA', (old_width, old_height), (0, 0, 0, 0))
                frame.paste(input_image, (0, 0), input_image)
                frame.paste(background_image, (0, 0), background_image)
                frames.append(frame)
            return flask_utils.serve_pil_gif_image(frames, 100)
