from numba import njit
from typing import Union
from src.shared.typings import GrayImage
from .config import hpBarAllowedPixelsColors, manaBarAllowedPixelsColors
from .extractors import getHpBar, getManaBar
from .locators import getHpIconPosition, getManaIconPosition


# TODO: add parameters types
# TODO: add unit tests
# TODO: add perf
@njit(cache=True, fastmath=True)
def getFilledBarPercentage(bar, allowedPixelsColors=[]) -> int:
    barPercent = len(bar)
    for i in range(len(bar)):
        if bar[i] not in allowedPixelsColors:
            barPercent -= 1
    return (barPercent * 100 // 94)


# Ein Balken, in dem fast KEIN Pixel eine bekannte Balkenfarbe hat, ist
# kein fast leerer Balken - er ist ein unbrauchbares Bild. Genau das
# passierte, als das Bild verlustbehaftet (JPEG) geholt wurde: von 94
# Pixeln behielt eines seinen exakten Wert, der Bot las "1 %" und heilte
# ununterbrochen. Bei echtem Lebensverlust bleibt der gefuellte Teil
# farblich intakt, nur kuerzer - dieser Fall wird also nicht getroffen.
# Lieber gar nichts wissen (None) als eine erfundene 1.
UNBRAUCHBAR_AB = 2


def _plausibel(prozent: int, bar) -> bool:
    if prozent > UNBRAUCHBAR_AB:
        return True
    # Ein wirklich fast leerer Balken hat einen einheitlichen Hintergrund.
    # Ein kaputtes Bild rauscht.
    return len(set(bar.tolist())) <= 3


# TODO: add unit tests
# PERF: [0.34756980000000004, 2.9999999999752447e-06]
def getHpPercentage(screenshot: GrayImage) -> Union[int, None]:
    hpIconPosition = getHpIconPosition(screenshot)
    if hpIconPosition is None:
        return None
    bar = getHpBar(screenshot, hpIconPosition)
    prozent = getFilledBarPercentage(
        bar, allowedPixelsColors=hpBarAllowedPixelsColors)
    return prozent if _plausibel(prozent, bar) else None


# TODO: add unit tests
# PERF: [0.32003090000000034, 3.200000000092018e-06]
def getManaPercentage(screenshot: GrayImage) -> Union[int, None]:
    manaIconPosition = getManaIconPosition(screenshot)
    if manaIconPosition is None:
        return None
    bar = getManaBar(screenshot, manaIconPosition)
    prozent = getFilledBarPercentage(
        bar, allowedPixelsColors=manaBarAllowedPixelsColors)
    return prozent if _plausibel(prozent, bar) else None
