"""Script to autogenerate typing.py with all int/uint Literal types and custom tuple types.

This script creates the typing definitions for ABI type strings, including all integer, bytes, and tuple variants.
"""
import itertools
from pathlib import (
    Path,
)

HEADER = """# AUTOGENERATED FILE. DO NOT EDIT DIRECTLY.
from typing import (
    Literal,
    TypeVar,
    Union,
)

T = TypeVar("T")

IntegerTypeStr = Union["IntTypeStr", "UintTypeStr"]

AddressTypeStr = Literal["address"]
BoolTypeStr = Literal["bool"]
StringTypeStr = Literal["string"]

AddressArrayTypeStr = Literal["address[]"]
StringArrayTypeStr = Literal["string[]"]
BoolArrayTypeStr = Literal["bool[]"]

ArrayTypeStr = Union[
    "AddressArrayTypeStr",
    "BoolArrayTypeStr",
    "BytesArrayTypeStr",
    "IntArrayTypeStr",
    "StringArrayTypeStr",
]

TupleTypeStr = Union[
    "TupleAddressIntTypeStr",
    "TupleBoolIntTypeStr",
    "TupleBytesIntTypeStr",
    "TupleIntIntTypeStr",
    "TupleStrIntTypeStr",
]

"""

INT_SUFFIXES = range(8, 257, 8)
INT_TYPES = [f'"int{i}"' for i in INT_SUFFIXES]
UINT_TYPES = [f'"uint{i}"' for i in INT_SUFFIXES]
ALL_INT_TYPES = INT_TYPES + UINT_TYPES
BYTES_TYPES = ["bytes"] + [f"bytes{i}" for i in range(1, 33)]


def gen_int_types(prefix: str, suffix: str, int_types: list[str]) -> list[str]:
    return [f'"{prefix}{t[1:-1]}{suffix}"' for t in int_types]


def write_typing_py():
    int_types = ",\n    ".join(INT_TYPES)
    uint_types = ",\n    ".join(UINT_TYPES)

    address_int_types = ",\n    ".join(gen_int_types("(address,", ")", ALL_INT_TYPES))
    bool_int_types = ",\n    ".join(gen_int_types("(bool,", ")", ALL_INT_TYPES))
    bytes_int_types = ",\n    ".join(gen_int_types("(bytes,", ")", ALL_INT_TYPES))
    string_int_types = ",\n    ".join(gen_int_types("(string,", ")", ALL_INT_TYPES))

    bytes_types = ",\n    ".join(f'"{t}"' for t in BYTES_TYPES)
    bytes_array_types = ",\n    ".join(f'"{t}[]"' for t in BYTES_TYPES)

    int_array_types = ",\n    ".join(f'{t[:-1]}[]"' for t in ALL_INT_TYPES)
    int_int_types = ",\n    ".join(
        f'"({a[1:-1]},{b[1:-1]})"'
        for a, b in itertools.product(ALL_INT_TYPES, repeat=2)
    )

    content = HEADER
    content += f"""
IntTypeStr = Literal[
    {int_types},
]

UintTypeStr = Literal[
    {uint_types},
]

BytesTypeStr = Literal[
    {bytes_types},
]

IntArrayTypeStr = Literal[
    {int_array_types},
]

BytesArrayTypeStr = Literal[
    {bytes_array_types},
]

# New tuple type strings
TupleAddressIntTypeStr = Literal[
    {address_int_types},
]

TupleBoolIntTypeStr = Literal[
    {bool_int_types},
]

TupleBytesIntTypeStr = Literal[
    {bytes_int_types},
]

TupleIntIntTypeStr = Literal[
    {int_int_types},
]

TupleStrIntTypeStr = Literal[
    {string_int_types},
]

AnyTypeStr = Union[
    AddressTypeStr,
    BoolTypeStr,
    StringTypeStr,
    AddressArrayTypeStr,
    StringArrayTypeStr,
    BoolArrayTypeStr,
    ArrayTypeStr,
    TupleTypeStr,
    BytesTypeStr,
    IntTypeStr,
    UintTypeStr,
    str,
]
"""

    Path("faster_eth_abi/typing.py").write_text(content.strip() + "\n")


if __name__ == "__main__":
    write_typing_py()
