import weakref
from os import path as op
from traceback import extract_stack, format_list

import numpy as np
from numpy.typing import NDArray

from ..util import logger
from .globject import GLObject

# -----------------------------------------------------------------------------
# Copyright (c) Vispy Development Team. All Rights Reserved.
# Distributed under the (new) BSD License. See LICENSE.txt for more info.
# -----------------------------------------------------------------------------

# ------------------------------------------------------------ Buffer class ---
class Buffer(GLObject):
    def __init__(self, data: NDArray | None = None, nbytes: None | int = None): ...
    @property
    def nbytes(self): ...
    def set_subdata(self, data: NDArray, offset: int = 0, copy: bool = False): ...
    def set_data(self, data: NDArray, copy: bool = False): ...
    def resize_bytes(self, size: int): ...

# -------------------------------------------------------- DataBuffer class ---
class DataBuffer(Buffer):
    def __init__(self, data: NDArray | None = None): ...
    def _prepare_data(self, data): ...
    def set_subdata(self, data: NDArray, offset: int = 0, copy: bool = False, **kwargs): ...
    def set_data(self, data: NDArray, copy: bool = False, **kwargs): ...
    @property
    def dtype(self): ...
    @property
    def offset(self): ...
    @property
    def stride(self): ...
    @property
    def size(self): ...
    @property
    def itemsize(self): ...
    @property
    def glsl_type(self): ...
    def resize_bytes(self, size: int): ...
    def __getitem__(self, key): ...
    def __setitem__(self, key, data): ...
    def __repr__(self): ...

class DataBufferView(DataBuffer):
    # Note that this class is a bit evil: it is a subclass of GLObject,
    # Buffer and DataBuffer, but any of these __init__'s are not called ...

    def __init__(self, base: DataBuffer, key: str | int | slice): ...
    @property
    def glir(self): ...
    @property
    def id(self): ...
    @property
    def _last_dim(self): ...
    def set_subdata(self, data: NDArray, offset: int = 0, copy: bool = False, **kwargs): ...
    def set_data(self, data: NDArray, copy: bool = False, **kwargs): ...
    @property
    def offset(self): ...
    @property
    def base(self): ...
    def resize_bytes(self, size: int): ...
    def __getitem__(self, key): ...
    def __setitem__(self, key, data): ...
    def __repr__(self): ...

# ------------------------------------------------------ VertexBuffer class ---
class VertexBuffer(DataBuffer):
    _GLIR_TYPE: str = ...

    def _prepare_data(self, data, convert=False): ...

def _last_stack_str(): ...

# ------------------------------------------------------- IndexBuffer class ---
class IndexBuffer(DataBuffer):
    _GLIR_TYPE: str = ...

    def __init__(self, data: NDArray | None = None): ...
    def _prepare_data(self, data, convert=False): ...
