from pathlib import Path

from PIL import Image

from arcade.hitbox import HitBoxAlgorithm
from arcade.resources import resolve

from .spritesheet import SpriteSheet
from .texture import ImageData, Texture


def load_texture(
    file_path: str | Path,
    *,
    hit_box_algorithm: HitBoxAlgorithm | None = None,
    hash: str | None = None,
) -> Texture:
    """
    Load a texture from disk (no caching).

    When loading a texture a set of hit box points will be generated by default
    based on the pixel data. The default hit box algorithm is a simple 4 to 8
    point hit box. This can be overridden by passing a different hit box or
    the global default can be set in the hitbox module.

    Examples::

        # We can load a texture using resource handles, string path or Path object
        texture = load_texture(":resources:image.png")
        texture = load_texture("image.png")
        texture = load_texture(Path("image.png"))

        # We can also specify a hit box algorithm to use for this texture
        texture = load_texture(
            ":resources:images/enemies/slimeBlock.png",
            hit_box_algorithm=arcade.hitbox.algo_detailed.
        )

    Args:
        file_path:
            Path to the image file
        hit_box_algorithm:
            The hit box algorithm to use for this texture. If not specified
            the global default will be used.
        hash:
            (advanced) Optional custom hash/name for the loaded image.
            This is used for texture caching and global uniqueness
            in texture atlases.
    """
    if isinstance(file_path, str):
        file_path = resolve(file_path)

    im: Image.Image = Image.open(file_path)  # type: ignore
    if im.mode != "RGBA":
        im = im.convert("RGBA")

    im_data = ImageData(im, hash=hash)
    tex = Texture(im_data, hit_box_algorithm=hit_box_algorithm)
    tex.file_path = file_path
    return tex


def load_image(
    file_path: str | Path,
    *,
    mode: str = "RGBA",
) -> Image.Image:
    """
    Load a Pillow image from disk (no caching).

    Normally you would use ``load_texture`` instead of this function.
    This function is useful when you want to load an image and then
    manipulate it before creating a texture.

    Note that Arcade mainly works with RGBA images. If you override
    the mode you might need to convert the final image to RGBA.

    Args:
        file_path:
            Path to the image file
        mode:
            The desired mode for the image (default: "RGBA")
    """
    if isinstance(file_path, str):
        file_path = resolve(file_path)

    im: Image.Image = Image.open(file_path)  # type: ignore
    if im.mode != mode:
        im = im.convert(mode)

    return im


def load_spritesheet(file_name: str | Path) -> SpriteSheet:
    """
    Loads an image from disk returning a sprite sheet that can
    further be used to slice out smaller images.

    Args:
        file_name: Path to the image file
    """
    if isinstance(file_name, str):
        file_name = resolve(file_name)

    im: Image.Image = Image.open(file_name)
    if im.mode != "RGBA":
        im = im.convert("RGBA")

    return SpriteSheet.from_image(im)
