from numpy.typing import ArrayLike
from typing import Mapping, Callable
from vispy.gloo.context import GLContext
from vispy.scene.widgets.widget import Widget
from vispy.app.application import Application
from vispy.keys import Key
from vispy.app.canvas import Canvas, MouseEvent

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

from __future__ import division, print_function

import sys
import numpy as np
from time import sleep

from ..util.event import EmitterGroup, Event, WarningEmitter
from ..util.ptime import time
from ..util.dpi import get_dpi
from ..util import config as util_config, logger
from . import Application, use_app
from ..gloo.context import GLContext, set_current_canvas, forget_canvas
from ..gloo import FrameBuffer, RenderBuffer

# todo: add functions for asking about current mouse/keyboard state
# todo: add hover enter/exit events
# todo: add focus events

class Canvas(object):
    def __init__(
        self,
        title: str = "VisPy canvas",
        size: tuple[float, float] = ...,
        position: tuple[float, float] | None = None,
        show: bool = False,
        autoswap: bool = True,
        app: str | Application | None = None,
        create_native: bool = True,
        vsync: bool = False,
        resizable: bool = True,
        decorate: bool = True,
        fullscreen: bool | int = False,
        config: Mapping | None = None,
        shared: None | Canvas | GLContext = None,
        keys: str | Mapping | None = None,
        parent: Widget | None = None,
        dpi: None | float = None,
        always_on_top: bool = False,
        px_scale: int = 1,
        backend_kwargs: Mapping | None = None,
    ): ...
    def create_native(self): ...
    def _set_keys(self, keys): ...
    @property
    def context(self): ...
    @property
    def app(self): ...
    @property
    def native(self): ...
    @property
    def dpi(self): ...
    @dpi.setter
    def dpi(self, dpi): ...
    def connect(self, fun: Callable): ...

    # ---------------------------------------------------------------- size ---
    @property
    def size(self): ...
    @size.setter
    def size(self, size): ...
    @property
    def physical_size(self): ...
    @property
    def pixel_scale(self): ...
    @property
    def fullscreen(self): ...
    @fullscreen.setter
    def fullscreen(self, fullscreen): ...

    # ------------------------------------------------------------ position ---
    @property
    def position(self): ...
    @position.setter
    def position(self, position): ...

    # --------------------------------------------------------------- title ---
    @property
    def title(self): ...
    @title.setter
    def title(self, title): ...

    # ----------------------------------------------------------------- fps ---
    @property
    def fps(self): ...
    def set_current(self, event=None): ...
    def swap_buffers(self, event=None): ...
    def show(self, visible: bool = True, run: bool = False): ...
    def update(self, event=None): ...
    def close(self): ...
    def _update_fps(self, event): ...
    def measure_fps(self, window: float = 1, callback: Callable | str = "%1.1f FPS"): ...

    # ---------------------------------------------------------------- misc ---
    def __repr__(self): ...
    def _repr_mimebundle_(self, *args, **kwargs): ...
    def _ipython_display_(self): ...
    def __enter__(self): ...
    def __exit__(self, type, value, traceback): ...
    def render(self, alpha: bool = True) -> ArrayLike: ...

# Event subclasses specific to the Canvas
class MouseEvent(Event):
    def __init__(
        self,
        type: str,
        pos: tuple[int, int] | None = None,
        button: None | int = None,
        buttons: tuple[int, ...] | None = None,
        modifiers: tuple[Key, ...] | None = None,
        delta: tuple[float, float] | None = None,
        last_event: MouseEvent | None = None,
        press_event: MouseEvent | None = None,
        **kwargs,
    ): ...
    @property
    def pos(self): ...
    @property
    def button(self): ...
    @property
    def buttons(self): ...
    @property
    def modifiers(self): ...
    @property
    def delta(self): ...
    @property
    def press_event(self): ...
    @property
    def last_event(self): ...
    @property
    def time(self): ...
    def _forget_last_event(self): ...
    @property
    def is_dragging(self): ...
    def drag_events(self): ...
    def trail(self): ...

class KeyEvent(Event):
    def __init__(self, type: str, key: Key | None = None, text: str = "", modifiers: tuple[Key, ...] | None = None, **kwargs): ...
    @property
    def key(self): ...
    @property
    def text(self): ...
    @property
    def modifiers(self): ...

class ResizeEvent(Event):
    def __init__(
        self, type: str, size: tuple[int, int] | None = None, physical_size: tuple[int, int] | None = None, **kwargs
    ): ...
    @property
    def size(self): ...
    @property
    def physical_size(self): ...

class DrawEvent(Event):
    def __init__(self, type: str, region: tuple[int, int, int, int] | None = None, **kwargs): ...
    @property
    def region(self): ...
