from sh import convert as conv_unbaked, composite as comp_unbaked, identify as ident_unbaked
import logging
import magic
import re
from . import command, photo_fn, update_to_message
from io import StringIO, BytesIO

logger = logging.getLogger("scale")
config = None

# disable _tty_out to compact the AppArmor profile :)
convert = conv_unbaked.bake(_tty_out=False)
composite = comp_unbaked.bake(_tty_out=False)
identify = ident_unbaked.bake(_tty_out=False)

mime_detector = magic.Magic(mime=True)

def get_file_dims(fname):
    s = StringIO()
    identify(fname, _out=s)
    string = s.getvalue()
    return [*map(int, (string.split()[2]).split('x'))]

@update_to_message
def rescale_bypass(message):
    txt = ""
    if (message.reply_to_message):
        txt = message.text
    else:
        txt = message.caption
    return (message.chat_id in config['autorescale_chat_ids']) and (not txt or not txt.startswith('Bea'))

def rescale_image(image_io, extension):
    size = '35%'
    xresize = 35
    yresize = 35

    fname = 'cas'+extension

    with open(fname, 'wb') as f:
        f.write(image_io.read())

    sz = get_file_dims(fname)
    transformed_width = sz[0] * (xresize/100)
    transformed_height = sz[1] * (yresize/100)

    result_size = transformed_width * transformed_height
    if result_size > 10e6:
        raise ValueError("resulting image would be too big (>10MP)")

    convert(fname, '-liquid-rescale', size, 'output.png')
    convert('output.png', '-liquid-rescale', f"{sz[0]}x{sz[1]}", 'output2.png')
    final_file = 'output2.png'

    data = open(final_file, 'rb')
    return data


@command('(?:rescale|herschaliseer)',
         pass_groups=True, additional_match_fn=photo_fn, bypass_fn=rescale_bypass)
def rescale(bea, bot, update, photo, groups):
    """ Content-aware scale an image. """
    if (hasattr(photo, "width")):
        sz = photo.width, photo.height
    elif (not photo.file_size):
        return update.message.reply_text("Is this a file? If so, it won't tell me its file size, so I won't download it.")
    elif (photo.file_size > 10e6):
        return update.message.reply_text("10 megabytes is too big for me chief.")

    buf = BytesIO()

    fl = photo.get_file()
    fl.download(out=buf)
    buf.seek(0)

    mimetype = mime_detector.from_buffer(buf.getvalue())
    if (mimetype == 'image/png'):
        extension = '.png'
    elif (mimetype == 'image/jpeg'):
        extension = '.jpg'
    else:
        logger.info(f"Got 'photo' with MIME type {mimetype}.")
        return


    bea.start_uploading_photo()

    try:
        f = rescale_image(buf, extension)
    except ValueError as e:
        return bea.reply(f"rescale error: {e}")

    bea.stop_uploading_photo()
    update.message.reply_photo(photo=f)

@command('nepsticker', additional_match_fn=photo_fn)
def webp_convert(bea, bot, update, photo):
    """ Turn an image into a 'fake sticker', i.e. a .webp image. """
    photo.get_file().download('webpin.png')
    convert('webpin.png', '-resize', '512x512', 'webpout.webp')
    update.message.reply_sticker(open('webpout.webp', 'rb'))

def parse_string_with_quotes(s):
    STATE_IN_QUOTE = 1
    STATE_NORMAL = 0
    state = STATE_NORMAL
    res = []
    temp = ""
    for c in s:
        if state == STATE_IN_QUOTE:
            if c == '"':
                state = STATE_NORMAL
            else:
                temp += c
        else:
            if c == '"':
                state = STATE_IN_QUOTE
            elif c.isspace():
                res += [temp]
                temp = ""
            else:
                temp += c
    res += [temp]
    return res

@command('convert (.+)', additional_match_fn=photo_fn, pass_groups=True, auth=True)
def im_command(bea, bot, update, photo, groups):
    photo.get_file().download('im_in.png')
    convert('im_in.png', *parse_string_with_quotes(groups[0]), 'im_out.png')
    update.message.reply_photo(photo=open('im_out.png', 'rb'))

@command('512', additional_match_fn=photo_fn)
def stickersize(bea, bot, update, photo):
    """
    Turn an image into a 512x512 png file, ready to be stickerified. Also take a look at Bea's sticker features!
    """
    photo.get_file().download('stickerin.png')
    convert('stickerin.png', '-resize', '512x512', 'stickerout.png')
    update.message.reply_document(document=open('stickerout.png', 'rb'), filename='sticker.png')

def init(bea, _config):
    global config
    config = _config
    return [rescale, webp_convert, im_command, stickersize]
