# Copyright © 2025 GlacieTeam.All rights reserved.
#
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy
# of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# SPDX-License-Identifier: MPL-2.0

from typing import overload, List, Any, Dict
from .snbt_format import SnbtFormat, SnbtNumberFormat
from .tag_type import TagType
from .tag import Tag

class CompoundTagVariant:
    """
    A warpper of all tags, to provide morden API for NBT
    """

    def __bytes__(self) -> bytes:
        """
        Implicitly convert to bytes
        """

    def __contains__(self, index: str) -> bool:
        """
        Check if the value is in the CompoundTag.
        Throw TypeError is not hold a CompoundTag.
        """

    def __eq__(self, other: CompoundTagVariant) -> bool:
        """
        Check if this tag equals another tag
        """

    def __float__(self) -> float:
        """
        Implicitly convert to float
        """

    @overload
    def __getitem__(self, index: int) -> CompoundTagVariant:
        """
        Get value by object key
        """

    @overload
    def __getitem__(self, index: str) -> CompoundTagVariant:
        """
        Get value by array index
        """

    def __len__(self) -> int:
        """
        Get the hash of the tag
        """

    @overload
    def __init__(self) -> None:
        """
        Default Constructor
        """

    @overload
    def __init__(self, value: Any) -> None:
        """
        Construct from any Python object
        """

    def __int__(self) -> int:
        """
        Implicitly convert to int
        """

    def __iter__(self) -> List[CompoundTagVariant]:
        """
        Iterate over tags in the tag variant
        """

    def __len__(self) -> int:
        """
        Get the size of the tag
        """

    def __repr__(self) -> str:
        """
        Official string representation
        """

    @overload
    def __setitem__(self, index: str, value: Any) -> None:
        """
        Set value by object key
        """

    @overload
    def __setitem__(self, index: int, value: Any) -> None:
        """
        Set value by array index
        """

    def __str__(self) -> str:
        """
        String representation (SNBT minimized format)
        """

    def append(self, value: Any, check_type: bool = True) -> None:
        """
        Append a Tag element if self is ListTag
        Throw TypeError if wrong type and check_type is True

        Args:
            value (Any): value append to ListTag
            check_type (bool): check value type is same as the type that ListTag holds
        """

    def assign(self, value: Any) -> None:
        """
        Assign value
        """

    def as_tag(self) -> Tag:
        """
        Convert to a Tag
        """

    def check_and_fix_list_elements(self) -> bool:
        """
        Check the whether elements in this ListTag is the same, and fix it."
        Throw type error is self is not a ListTag.
        """

    def get_byte(self, signed: bool = False) -> int:
        """
        Get the byte value
        Throw TypeError if wrong type
        """

    def get_bytes(self) -> bytes:
        """
        Get the original string value (bytes in StringTag)
        Throw TypeError if wrong type
        """

    def get_byte_array(self) -> bytes:
        """
        Get the byte array value
        Throw TypeError if wrong type
        """

    def get_compound(self) -> Dict[str, CompoundTagVariant]:
        """
        Get the CompoundTag as a dict value
        Throw TypeError if wrong type
        """

    def get_double(self) -> float:
        """
        Get the double value
        Throw TypeError if wrong type
        """

    def get_float(self) -> float:
        """
        Get the float value
        Throw TypeError if wrong type
        """

    def get_int(self, signed: bool = True) -> int:
        """
        Get the int value
        Throw TypeError if wrong type
        """

    def get_long(self, signed: bool = True) -> int:
        """
        Get the int64 value
        Throw TypeError if wrong type
        """

    def get_int_array(self) -> List[int]:
        """
        Get the int array value
        Throw TypeError if wrong type
        """

    def get_list(self) -> List[CompoundTagVariant]:
        """
        Get the ListTag as a list value
        Throw TypeError if wrong type
        """

    def get_long_array(self) -> List[int]:
        """
        Get the long array value
        Throw TypeError if wrong type
        """

    def get_short(self, signed: bool = True) -> int:
        """
        Get the short value
        Throw TypeError if wrong type
        """

    def get_string(self) -> str:
        """
        Get the string value
        Throw TypeError if wrong type
        """

    @overload
    def contains(self, index: str) -> bool:
        """
        Check if the value is in the CompoundTag.
        Throw TypeError is not hold a CompoundTag.
        """

    @overload
    def contains(self, key: str, type: TagType) -> bool:
        """
        Check if the value is in the CompoundTag and value type is the specific type.
        Throw TypeError is not hold a CompoundTag.
        """

    def clear(self) -> None:
        """
        Clear the data in the tag
        Throw TypeError if the tag can not be cleared.
        """

    def copy(self) -> Tag:
        """
        Create a deep copy of this tag
        """

    def get_type(self) -> TagType:
        """
        Get the NBT type ID
        """

    def hash(self) -> int:
        """
        Get the hash of the tag
        """

    def hold(self, type: TagType) -> bool:
        """
        Check the NBT type ID
        """

    def is_array(self) -> bool:
        """
        Check whether the tag is a ListTag
        """

    def is_binary(self) -> bool:
        """
        Check whether the tag is a binary tag
        Example:
            ByteArrayTag, IntArrayTag, LongArrayTag
        """

    def is_boolean(self) -> bool:
        """
        Check whether the tag is a ByteTag
        """

    def is_null(self) -> bool:
        """
        Check whether the tag is an EndTag (Tag not exists)
        """

    def is_number(self) -> bool:
        """
        Check whether the tag is a number based tag
        Example:
            ByteTag, ShortTag, IntTag, LongTag, FloatTag, DoubleTag
        """

    def is_number_float(self) -> bool:
        """
        Check whether the tag is a float number based tag
        Example:
            FloatTag, DoubleTag
        """

    def is_number_integer(self) -> bool:
        """
        Check whether the tag is a integer number based tag
        Example:
            ByteTag, ShortTag, IntTag, LongTag
        """

    def is_object(self) -> bool:
        """
        Check whether the tag is a CompoundTag
        """

    def is_primitive(self) -> bool:
        """
        Check whether the tag is a primitive tag
        Example:
            ByteTag, ShortTag, IntTag, LongTag, FloatTag, DoubleTag, StringTag, ByteArrayTag, IntArrayTag, LongArrayTag
        """

    def is_string(self) -> bool:
        """
        Check whether the tag is a StringTag
        """

    def is_structured(self) -> bool:
        """
        Check whether the tag is a structured tag
        Example:
            CompoundTag, ListTag
        """

    def items(self) -> list:
        """
        Get list of (key, value) pairs in this tag
        Throw TypeError if wrong type
        """

    def load(self, stream: ...) -> None:
        """
        Load tag value from a binary stream
        """

    def merge(self, other: CompoundTagVariant, merge_list: bool = False) -> None:
        """
        Merge another CompoundTag into this one

        Arguments:
            other: CompoundTag to merge from
            merge_list: If true, merge list contents instead of replacing
        """

    @overload
    def pop(self, index: str) -> bool:
        """
        Remove key from the CompoundTag
        Throw TypeError if wrong type
        """

    @overload
    def pop(self, index: int) -> bool:
        """
        Remove key from the ListTag
        Throw TypeError if wrong type
        """

    def rename(self, index: str, new_name: str) -> bool:
        """
        Rename a key in the CompoundTag
        Throw TypeError if wrong type
        """

    def size(self) -> int:
        """
        Get the size of the tag
        """

    def to_json(self, indent: int = 4) -> str:
        """
        Convert tag to JSON string
        """

    def to_snbt(
        self,
        snbt_format: SnbtFormat = SnbtFormat.Default,
        indent: int = 4,
        number_format: SnbtNumberFormat = SnbtNumberFormat.Decimal,
    ) -> str:
        """
        Convert tag to SNBT string
        """

    def write(self, stream: ...) -> None:
        """
        Write tag to a binary stream
        """

    @property
    def value(self) -> Any:
        """
        Access the tag value
        """

    @value.setter
    def value(self, value: Any) -> None:
        """
        Access the tag value
        """
