import os

import cv2
import numpy as np
import torch
from loguru import logger

from libs.helper import pad_img_to_modulo, download_model, norm_img, get_cache_path_by_url
from libs.model.base import InpaintModel
from libs.schema import Config

model_url = 'https://ae-rt.oss-cn-beijing.aliyuncs.com/matting_module/inpaint/big-lama.pt'
if 'ay-' in os.uname()[1]:
    model_url = 'https://ae-rt.oss-cn-beijing-internal.aliyuncs.com/matting_module/inpaint/big-lama.pt'

LAMA_MODEL_URL = os.environ.get(
    "LAMA_MODEL_URL",
    model_url
    #"https://github.com/Sanster/models/releases/download/add_big_lama/big-lama.pt",
)


class LaMa(InpaintModel):
    pad_mod = 8

    def __init__(self, device):
        """

        Args:
            device:
        """
        super().__init__(device)
        self.device = device

    def init_model(self, device):
        if os.environ.get("LAMA_MODEL"):
            model_path = os.environ.get("LAMA_MODEL")
            if not os.path.exists(model_path):
                raise FileNotFoundError(
                    f"lama torchscript model not found: {model_path}"
                )
        else:
            model_path = download_model(LAMA_MODEL_URL)
        logger.info(f"Load LaMa model from: {model_path}")
        model = torch.jit.load(model_path, map_location="cpu")
        model = model.to(device)
        model.eval()
        self.model = model
        self.model_path = model_path

    @staticmethod
    def is_downloaded() -> bool:
        return os.path.exists(get_cache_path_by_url(LAMA_MODEL_URL))

    def forward(self, image, mask, config: Config):
        """Input image and output image have same size
        image: [H, W, C] RGB
        mask: [H, W]
        return: BGR IMAGE
        """
        image = norm_img(image)
        mask = norm_img(mask)

        mask = (mask > 0) * 1
        image = torch.from_numpy(image).unsqueeze(0).to(self.device)
        mask = torch.from_numpy(mask).unsqueeze(0).to(self.device)

        inpainted_image = self.model(image, mask)

        cur_res = inpainted_image[0].permute(1, 2, 0).detach().cpu().numpy()
        cur_res = np.clip(cur_res * 255, 0, 255).astype("uint8")
        cur_res = cv2.cvtColor(cur_res, cv2.COLOR_RGB2BGR)
        return cur_res
