import os
from typing import Union, List
from .CompressionHelper import BROTLI_MAGIC, GZIP_MAGIC
from ..enums import FileType
from ..streams import EndianBinaryReader


def file_name_without_extension(file_name: str) -> str:
    return os.path.join(
        os.path.dirname(file_name), os.path.splitext(os.path.basename(file_name))[0]
    )


def list_all_files(directory: str) -> List[str]:
    return [
        val
        for sublist in [
            [os.path.join(dir_path, filename) for filename in filenames]
            for (dir_path, dirn_ames, filenames) in os.walk(directory)
            if ".git" not in dir_path
        ]
        for val in sublist
    ]


def find_all_files(directory: str, search_str: str) -> List[str]:
    return [
        val
        for sublist in [
            [
                os.path.join(dir_path, filename)
                for filename in filenames
                if search_str in filename
            ]
            for (dir_path, dirn_ames, filenames) in os.walk(directory)
            if ".git" not in dir_path
        ]
        for val in sublist
    ]


def check_file_type(input_) -> Union[FileType, EndianBinaryReader]:
    if isinstance(input_, str) and os.path.isfile(input_):
        reader = EndianBinaryReader(open(input_, "rb"))
    elif isinstance(input_, EndianBinaryReader):
        reader = input_
    else:
        try:
            reader = EndianBinaryReader(input_)
        except:
            return None, None

    if reader.Length < 20:
        return FileType.ResourceFile, reader

    signature = reader.read_string_to_null(20)
    reader.Position = 0
    if signature in [
        "UnityWeb",
        "UnityRaw",
        "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA",
        "UnityFS",
    ]:
        return FileType.BundleFile, reader
    elif signature == "UnityWebData1.0":
        return FileType.WebFile, reader
    elif signature == "PK\x03\x04":
        return FileType.ZIP, reader
    else:
        if reader.Length < 128:
            return FileType.ResourceFile, reader

        magic = bytes(reader.read_bytes(2))
        reader.Position = 0
        if GZIP_MAGIC == magic:
            return FileType.WebFile, reader
        reader.Position = 0x20
        magic = bytes(reader.read_bytes(6))
        reader.Position = 0
        if BROTLI_MAGIC == magic:
            return FileType.WebFile, reader

        # check if AssetsFile
        old_endian = reader.endian
        # read as if assetsfile and check version
        # ReadHeader
        reader.Position = 0
        metadata_size = reader.read_u_int()
        file_size = reader.read_u_int()
        version = reader.read_u_int()
        data_offset = reader.read_u_int()

        if version >= 22:
            endian = ">" if reader.read_boolean() else "<"
            reserved = reader.read_bytes(3)
            metadata_size = reader.read_u_int()
            file_size = reader.read_long()
            data_offset = reader.read_long()
            unknown = reader.read_long()  # unknown

        # reset
        reader.endian = old_endian
        reader.Position = 0
        # check info
        if any(
            (
                version < 0,
                version > 100,
                *[
                    x < 0 or x > reader.Length
                    for x in [file_size, metadata_size, version, data_offset]
                ],
                file_size < metadata_size,
                file_size < data_offset,
            )
        ):
            return FileType.ResourceFile, reader
        else:
            return FileType.AssetsFile, reader
