from __future__ import annotations
from typing import Any
from pathlib import Path

# DUK_TYPE_NONE: int = ...
# DUK_TYPE_UNDEFINED: int = ...
# DUK_TYPE_NULL: int = ...
# DUK_TYPE_BOOLEAN: int = ...
# DUK_TYPE_NUMBER: int = ...
# DUK_TYPE_STRING: int = ...
# DUK_TYPE_OBJECT: int = ...
# DUK_TYPE_BUFFER: int = ...
# DUK_TYPE_POINTER: int = ...
# DUK_TYPE_LIGHTFUNC: int = ...
# DUK_ENUM_OWN_PROPERTIES_ONLY: int = ...
# DUK_VARARGS: int = ...
# DUK_ERR_ERROR: int = ...

class DuktapeError(Exception): ...
class DuktapeFatalError(Exception): ...
class DuktapeThreadError(DuktapeError): ...
class JSError(Exception): ...

class DuktapeContext:
    def __init__(
        self, 
        disable_alterts: bool = False,
        disable_modules: bool = False
    ) -> None:
        """
        Initalizes a DuktapeContext

        :param disable_alterts: disables alterts such as alert() and print() respectively...
        :param disable_modules: disables the require function 
            Good for simulating html5 javascript where this should be disabled.
            This is bad if you need modules. It's best to leave this as false
            if this is the case.
        
        :raises DuktapeError: if the `duk_create_heap_default()` failes to create a C context

        """
        ...
    
    def set_globals(self, **kwargs: Any) -> None: ...
    def get_global(self, name: str | bytes) -> Any: ...
    def set_base_path(self, path: str | bytes | Path) -> None: ...
    def eval_js(self, src: str | bytes) -> object: ...
    def eval_js_file(self, src_path: str) -> None: ...
    def get_file_path(self, src_path: str) -> str: ...
    def make_jsref(self, index: int) -> JSRef: ...

class JSRef(object):
    def __init__(self, py_ctx: DuktapeContext, ref_index: int) -> None: ...
    def to_js(self) -> None: ...
    def __del__(self) -> None: ...

class JSProxy(object):
    def __init__(self, ref: JSRef, bind_proxy: JSProxy | object) -> None: ...
    def __setattr__(self, name: str, value: object) -> None: ...
    def __getattr__(self, name: str): ...
    def __getitem__(self, name: str) -> Any: ...
    def __repr__(self) -> str: ...
    def __call__(self, *args): ...
    def new(self, *args): ...
