import torch
import gradio as gr
import spaces
from inference_gradio import inference_one_image, model_init

MODEL_PATH = "./checkpoints/docres.pkl"
HEADER = """
<div align="center">
    <p>
        <span style="font-size: 30px; vertical-align: bottom;"> DocRes: A Generalist Model Toward Unifying Document Image Restoration Tasks </span>
    </p>
    <p style="margin-top: -15px;">
        <a href="https://arxiv.org/abs/2405.04408" target="_blank" style="color: grey;">ArXiv Paper</a>
        &nbsp;
        <a href="https://github.com/ZZZHANG-jx/DocRes" target="_blank" style="color: grey;">GitHub Repository</a>
    </p>
</div>

🖼️ Upload an image of a document (or choose one from examples below).  
✔️ Choose the tasks you want to perform on the document.  
🚀 Click "Run" and the model will enhance the document according to the selected tasks!
"""


possible_tasks = [
    "dewarping",
    "deshadowing",
    "appearance",
    "deblurring",
    "binarization",
]


@spaces.GPU(duration=60)
def run_tasks(image, tasks):
    device = "cuda" if torch.cuda.is_available() else "cpu"

    # load model
    model = model_init(MODEL_PATH, device)

    # run inference
    bgr_image = image[..., ::-1].copy()
    bgr_restored_image = inference_one_image(model, bgr_image, tasks, device)
    if bgr_restored_image.ndim == 3:
        rgb_image = bgr_restored_image[..., ::-1]
    else:
        rgb_image = bgr_restored_image

    return rgb_image


with gr.Blocks() as demo:
    gr.Markdown(HEADER)

    task = gr.CheckboxGroup(choices=possible_tasks, label="Tasks", value=["appearance"])
    with gr.Row():
        input_image = gr.Image(label="Raw Image", type="numpy")
        output_image = gr.Image(label="Enhanced Image", type="numpy")

    button = gr.Button()
    button.click(run_tasks, inputs=[input_image, task], outputs=[output_image])

    gr.Examples(
        examples=[
            ["input/218_in.png", ["dewarping", "deshadowing", "appearance"]],
            ["input/151_in.png", ["dewarping", "deshadowing", "appearance"]],
            ["input/for_debluring.png", ["deblurring"]],
            ["input/for_appearance.png", ["appearance"]],
            ["input/for_deshadowing.jpg", ["deshadowing"]],
            ["input/for_dewarping.png", ["dewarping"]],
            ["input/for_binarization.png", ["binarization"]],
        ],
        inputs=[input_image, task],
        outputs=[output_image],
        fn=run_tasks,
        cache_examples="lazy",
    )

demo.launch()