
from typing import NamedTuple, Any, Self, TypeVar, Generic, Iterator, Type, Tuple, Sequence, Iterable, overload, TypeAlias
from AppKit import NSBezierPath

NSLineCapStyle = int
NSLineJoinStyle = int
NSCompositingOperation = int
NSTextAlignment = int

NSPointLike: TypeAlias = "NSPoint | tuple[float, float]"
NSSizeLike: TypeAlias = "NSSize | tuple[float, float]"
NSRectLike: TypeAlias = "NSRect | tuple[NSPointLike, NSSizeLike]"

class NSPoint:
	x: float
	y: float
	def __init__(self, x: float = ..., y: float = ...) -> None: ...
	def __iter__(self) -> Iterator[float]: ...
	def __repr__(self) -> str: ...
	def __getitem__(self, key: int) -> float: ...
	def __len__(self) -> int: ...

class NSSize(NamedTuple):
	"""A size (width & height)."""
	width: float
	height: float
	def __getitem__(self, key: int) -> float: ...

class NSRect:
	"""A rectangle, defined by origin & size."""
	origin: NSPoint
	size: NSSize

	@classmethod
	def __new__(
		cls,
		origin: NSPointLike = NSPoint(0, 0),
		size: NSSizeLike = NSSize(0, 0),
	) -> "NSRect": ...
	def __getitem__(self) -> NSPoint: ...

class NSRange(NamedTuple):
	"""A range, defined by location & length."""
	location: int
	length: int

def NSMakePoint(x: float, y: float) -> NSPoint: ...
def NSMakeSize(width: float, height: float) -> NSSize: ...
def NSMakeRect(x: float, y: float, width: float, height: float) -> NSRect: ...
def NSMakeRange(location: int, length: int) -> NSRange: ...
def NSInsetRect(rect: NSRectLike, x: float, y: float) -> NSRect: ...
NSZeroRect: NSRect
NSZeroPoint: NSPoint

def NSMinX(rect: NSRectLike) -> float: ...
def NSMinY(rect: NSRectLike) -> float: ...
def NSMidX(rect: NSRectLike) -> float: ...
def NSMidY(rect: NSRectLike) -> float: ...
def NSMaxX(rect: NSRectLike) -> float: ...
def NSMaxY(rect: NSRectLike) -> float: ...
def NSWidth(rect: NSRectLike) -> float: ...
def NSHeight(rect: NSRectLike) -> float: ...


SEL = Any

def NSSelectorFromString(name: str) -> SEL: ...


class NSObject:
	@classmethod
	def new(cls) -> Self: ...
	@classmethod
	def alloc(cls) -> Self: ...
	def init(self) -> Self: ...
	def copy(self) -> Self: ...
	def description(self) -> str: ...
	def retain(self) -> Self: ...
	def release(self) -> None: ...
	def className(self) -> str: ...

	def valueForKey_(self, key: str) -> Any: ...
	def performSelector_withObject_afterDelay_(self, sel: SEL, obj: Any, delay: float) -> None: ...
	def bind_toObject_withKeyPath_options_(self, bind: str, object: Any, keyPath: "NSString" | str, options: "NSDictionary" | None) -> None: ...
	def unbind_(self, bind: str) -> None: ...
	def addObserver_forKeyPath_options_context_(self, observer: "NSObject", keyPath: str | "NSString", options: int, context: Any) -> None: ...
	def removeObserver_forKeyPath_context_(self, observer: "NSObject", keyPath: str | "NSString", context: Any) -> None: ...
	def removeObserver_forKeyPath_(self, observer: "NSObject", keyPath: str | "NSObject") -> None: ...


T = TypeVar("T", bound="NSObject")
KT = TypeVar("KT")
VT = TypeVar("VT")


class NSData(NSObject):
	@classmethod
	def dataWithContentsOfFile_(cls, path: str) -> Self: ...


class NSArray(NSObject, Generic[T]):
	def initWithObject_(self, value: Any) -> Self: ...
	def count(self) -> int: ...
	def __iter__(self) -> Iterator[T]: ...
	@classmethod
	def arrayWithArray_(cls, array: list | "NSArray") -> Self: ...


class NSMutableArray(NSArray, Generic[T]):
	def addObject_(self, obj: Any) -> None: ...
	def append(self, obj: Any) -> None: ...


def NSClassFromString(name: str) -> Type[NSObject]: ...


class NSDate(NSObject):
	def initWithTimeIntervalSince1970_(self, interval: float) -> Self: ...


class NSDictionary(Generic[KT, VT], NSObject):
	@classmethod
	def dictionary(cls) -> Self: ...
	def keysForObject_(self, obj: Any) -> list: ...
	@classmethod
	def dictionaryWithObject_forKey_(cls, objs: NSObject, keys: NSObject) -> Self: ...
	def __len__(self) -> int: ...
	def __iter__(self) -> Iterator[KT]: ...
	def items(self) -> Iterator[Tuple[KT, VT]]: ...
	def keys(self) -> Iterator[KT]: ...
	def values(self) -> Iterator[VT]: ...

class NSMutableDictionary(NSDictionary):
	def setObject_forKey_(self, obj: Any, key: Any) -> None: ...
	def __setitem__(self, key: NSObject | object, value: NSObject | object) -> None: ...
	def initWithDictionary_copyItems_(self, dictionary: NSDictionary | dict, copyItems: bool) -> Self: ...
	def pop(self) -> NSObject: ...


S = TypeVar("S")

class NSOrderedSet(Generic[S], Sequence[S]):
	@overload
	def __init__(self) -> None: ...
	@overload
	def __init__(self, items: Iterable[S]) -> None: ...
	def __init__(self, items: Iterable[Any] | None = None) -> None: ...

	@classmethod
	def orderedSetWithArray_(cls, items: Iterable[S]) -> "NSOrderedSet[S]": ...

	# Core Objective-C API
	def count(self) -> int: ...
	def objectAtIndex_(self, index: int) -> S: ...
	def firstObject(self) -> S: ...
	def lastObject(self) -> S: ...
	def indexOfObject_(self, obj: S) -> int: ...
	def containsObject_(self, obj: S) -> bool: ...

	# Python protocol methods
	def __len__(self) -> int: ...
	def __getitem__(self, index: int) -> S: ...
	def __iter__(self) -> Iterator[S]: ...


NSNotFound: int

class NSNull(NSObject):
	@classmethod
	def null(cls) -> "NSNull": ...

class NSNumber(NSObject):
	@classmethod
	def numberWithInt_(cls, number: int) -> "NSNumber": ...
	@classmethod
	def numberWithInteger_(cls, number: int) -> "NSNumber": ...
	@classmethod
	def numberWithFloat_(cls, number: float) -> "NSNumber": ...
	@classmethod
	def numberWithBool_(cls, number: bool) -> "NSNumber": ...
	def boolValue(self) -> bool: ...
	def floatValue(self) -> float: ...


class NSConcreteValue(NSObject):
	...


class NSString(NSObject):
	@classmethod
	def stringWithString_(cls, string: str | "NSString") -> "NSString": ...
	@classmethod
	def UUID(cls) -> "NSString": ...
	@classmethod
	def stringWithChar_(cls, char: int) -> "NSString": ...
	@classmethod
	def stringWithFormat_(cls: Type[T], format: "NSString", *args: Any) -> T: ...
	def sizeWithAttributes_(self, attributes: dict) -> NSSize: ...
	def drawInRect_withAttributes_(self, rect: NSRect, attributes: dict) -> None: ...
	def drawAtPoint_withAttributes_(self, pos: NSPoint, attributes: dict) -> None: ...
	def lastPathComponent(self) -> "NSString": ...
	@classmethod
	def drawTextAttributes_(cls, color: Any) -> dict: ...
	def drawAtPoint_color_alignment_handleSize_(self, pos: NSPoint, color: Any, aligment: int, handleSize: int) -> NSRect: ...

class NSAttributedString(NSObject):
	def initWithString_(self, string: str | NSString) -> Self: ...
	def initWithString_attributes_(self, string: str | NSString, attributes: dict | NSDictionary) -> Self: ...
	def drawAtPoint_alignment_(self, point: NSPointLike, alignment: int) -> None: ...
	def length(self) -> int: ...
	def size(self) -> NSSize: ...
	def drawAtPoint_(self, point: NSPointLike) -> None: ...

class NSMutableAttributedString(NSAttributedString):
	def appendAttributedString_(self, string: NSAttributedString) -> None: ...
	def instantiateWithOwner_topLevelObjects_(self, owner: Any, topLevelObjects: Any | None) -> bool: ...


class NSIndexSet(NSObject):
	@classmethod
	def indexSetWithIndexesInRange_(cls, range: NSRange) -> "NSIndexSet": ...


class NSAffineTransformStruct:
	m11: float
	m12: float
	m21: float
	m22: float
	tX: float
	tY: float

	@classmethod
	def __new__(
		cls,
		m11: float = 0,
		m12: float = 0,
		m21: float = 0,
		m22: float = 0,
		tX: float = 0,
		tY: float = 0,
	) -> Self: ...


class NSAffineTransform(NSObject):
	@classmethod
	def transform(cls) -> Self: ...
	def concat(self) -> None: ...
	def appendTransform_(self, transform: "NSAffineTransform") -> None: ...
	def translateXBy_yBy_(self, x: float, y: float) -> None: ...
	def scaleXBy_yBy_(self, x: float, y: float) -> None: ...
	def scaleBy_(self, scale: float) -> None: ...
	def rotateByDegrees_(self, angle: float) -> None: ...
	def transformStruct(self) -> NSAffineTransformStruct: ...
	def setTransformStruct_(self, ts: NSAffineTransformStruct | tuple) -> None: ...
	def transformPoint_(self, point: NSPoint) -> NSPoint: ...
	def transformBezierPath_(self, bezierPath: NSBezierPath) -> None: ...
	# implemented in Glyphs
	def shearXBy_yBy_atCenter_(self, xShear: float, yShear: float, center: NSPoint) -> None: ...
	def shearXBy_yBy_(self, xShear: float, yShear: float) -> None: ...
	def shearXBy_(self, xShear: float) -> None: ...
	def shearYBy_(self, yShear: float) -> None: ...
	def shearXBy_atCenter_(self, xShear: float, center: float) -> None: ...
	def shearYBy_atCenter_(self, yShear: float, center: float) -> None: ...


class NSURL(NSObject):
	@classmethod
	def URLWithString_(cls, path: str) -> "NSURL": ...
	@classmethod
	def fileURLWithPath_(cls, path: str | NSString) -> "NSURL": ...
	def path(self) -> str: ...


class NSNotificationCenter(NSObject):
	...

class NSTimer(NSObject):
	@classmethod
	def scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(cls, dur: float, target: Any, sel: SEL, userInfo: dict | None, repeats: bool) -> Self: ...
	def invalidate(self) -> None: ...

def NSLog(log: str): ...

def NSHomeDirectory() -> str: ...
