"""

to test the type annotations in a file
$ export MYPYPATH=src:Path/To/Glyphs/Scripts

then
$ mypy --ignore-missing-imports Path/To/Script/File.py

"""

import datetime
from typing import Any, List, Dict, Optional, Union, Generic, TypeVar, Type, NamedTuple, Iterator, Tuple, overload, Self, MutableMapping, Callable, deprecated
# from collections import OrderedDict
from Foundation import NSString, NSMutableArray, NSRect, NSPoint, NSRange, NSAffineTransform, NSAffineTransformStruct, NSOrderedSet, NSDictionary
from AppKit import NSObject, NSApplication, NSColor, NSBezierPath, NSPredicate, NSViewController, NSArrayController, NSError, NSView, NSStackView, NSImage, NSCursor, NSWindowController, NSDocument, NSTextStorage, NSEvent
from abc import ABC

F = TypeVar("F", bound=Callable[..., Any])

# G = TypeVar('G', bound='GSGlyph')
#
# class ListDict(List):
# 	items: List[G]
# 	def __getitem__(self, key: int | str) -> G: ...
# 	def __len__(self) -> int: ...
# 	def __iter__(self) -> Iterator[G]: ...


CFF: str = "CFF"
CFF2: str = "CFF2"
TT: str = "TT"
OTF: str = "OTF"
TTF: str = "TTF"
VARIABLE: str = "variableTT"
VariableTT: str = "variableTT"
VariableCFF: str = "variableCFF"
UFO: str = "UFO"
WOFF: str = "WOFF"
WOFF2: str = "WOFF2"
PLAIN: str = "plain"

T = TypeVar('T')
# K = TypeVar('K')  # Key type for mappings
V = TypeVar('V')  # Value type for mappings (can be T for sequences)

OwnerType = Union['GSFont', 'GSFontMaster', 'GSInstance']


class MGOrderedDictionary(dict):
	...


class OrderedDictProxy(Generic[T], ABC):  # T is the type of items in the sequence/values in mapping
	def __init__(self, owner: OwnerType) -> None: ...
	def __iter__(self) -> Iterator[T]: ...
	def __len__(self) -> int: ...
	def insert(self, index: int, value: T) -> None: ...
	@overload
	def __getitem__(self, key: int) -> T: ...
	@overload
	def __getitem__(self, key: str) -> T: ...
	@overload
	def __getitem__(self, key: slice) -> List[T]: ...
	def __setitem__(self, key: Union[int, str], value: T) -> None: ...
	def __delitem__(self, key: Union[int, str]) -> None: ...
	def pop(self, key: Union[int, str] = -1) -> T: ...
	def keys(self) -> List[str]: ...
	def items(self) -> Iterator[Tuple[str, T]]: ...
	def get(self, key: str, default: Any = None) -> T: ...
	def __contains__(self, key: Any) -> bool: ...
	def index(self, value: T) -> int: ...
	def append(self, value: T) -> None: ...
	def extend(self, values: List[T]) -> None: ...
	def clear(self) -> None: ...
	def remove(self, item: T) -> None: ...  # TODO: not enfored in each subclass.
	def values(self) -> List[T]: ...


class ListProxy(Generic[T], ABC):  # T is the type of items in the sequence
	def __init__(self, owner: OwnerType) -> None: ...
	def __iter__(self) -> Iterator[T]: ...
	def __len__(self) -> int: ...
	def insert(self, idx: int, value: T) -> None: ...
	def __getitem__(self, key: int) -> T: ...
	def __setitem__(self, key: int, value: T) -> None: ...
	def __delitem__(self, idx: Union[int, slice]) -> None: ...
	def pop(self, key: int = -1) -> T: ...
	def __contains__(self, key: Any) -> bool: ...
	def index(self, value: T) -> int: ...
	def remove(self, value: T) -> None: ...
	def values(self) -> List[T]: ...
	def extend(self, values: List[T]) -> None: ...
	def append(self, value: T) -> None: ...

class DictProxy(Generic[T], ABC):  # T is the type of items in the sequence
	def __init__(self, owner: OwnerType) -> None: ...
	def __len__(self) -> int: ...
	def __getitem__(self, key: str) -> T: ...
	def __setitem__(self, key: str, value: T) -> None: ...
	def __delitem__(self, key: str) -> None: ...
	def __iter__(self) -> Iterator[T]: ...
	def keys(self) -> List[str]: ...
	def items(self) -> Iterator[Tuple[str, T]]: ...
	def get(self, key: str, default: Any = None) -> Union[T, Any]: ...
	def __contains__(self, key: Any) -> bool: ...
	def pop(self, key: str, default: Any = None) -> Union[T, Any]: ...
	def clear(self) -> None: ...
	def append(self, value: T) -> None: ...
	def extend(self, values: List[T]) -> None: ...
	def remove(self, value: T) -> None: ...
	def values(self) -> List[T]: ...


class DefaultsProxy(MutableMapping[str, Any]):
	...

class GSGlyphMetrics(NamedTuple):
	width: float
	ascender: float
	descender: float
	italicAngle: float
	vertWidth: float
	slantHeight: float
	topHeight: float
	bottomHeight: float


class GSFont(NSObject):
	def __init__(self, path: Optional[str] = None) -> None: ...
	@property
	def parent(self) -> "GSDocument": ...
	masters: OrderedDictProxy["GSFontMaster"]
	def allMasters(self) -> list["GSFontMaster"]: ...
	instances: List["GSInstance"]
	def addInstance_(self, instance: "GSInstance") -> None: ...
	def removeInstanceAtIndex_(self, idx: int) -> None: ...
	axes: List["GSAxis"]
	properties: list
	metrics: OrderedDictProxy["GSMetric"]
	def setMetrics_(self, metrics: list["GSMetric"] | None) -> None: ...
	def addMetric_(self, metrics: "GSMetric") -> None: ...
	stems: OrderedDictProxy["GSMetric"]
	numbers: OrderedDictProxy["GSMetric"]

	glyphs: OrderedDictProxy["GSGlyph"]

	# def characterForGlyph(value: "GSGlyph") -> Any: ...
	def glyphForUnicode_(self, unicode: str) -> "GSGlyph" | None: ...
	def glyphForId_(self, Id: str) -> "GSGlyph" | None: ...
	def charStringFromDisplayString_(self, displayString: str) -> str: ...
	classes: OrderedDictProxy["GSClass"]
	features: OrderedDictProxy["GSFeature"]
	featurePrefixes: OrderedDictProxy["GSFeaturePrefix"]
	copyright: str
	@property
	def copyrights(self) -> Dict[str, str]: ...
	license: str
	@property
	def licenses(self) -> Dict[str, str]: ...
	compatibleFullName: str
	@property
	def compatibleFullNames(self) -> Dict[str, str]: ...
	sampleText: str
	@property
	def sampleTexts(self) -> Dict[str, str]: ...
	description: str
	@property
	def descriptions(self) -> DictProxy: ...
	designer: str
	@property
	def designers(self) -> dict[str, str]: ...
	trademark: str
	@property
	def trademarks(self) -> DictProxy: ...
	designerURL: str
	manufacturer: str
	@property
	def manufacturers(self) -> DictProxy: ...
	manufacturerURL: str
	versionMajor: int
	versionMinor: int
	date: datetime.datetime
	familyName: str
	fontName: str
	@property
	def familyNames(self) -> DictProxy: ...
	upm: int
	note: str
	kerning: dict
	kerningRTL: dict
	kerningVertical: dict
	def kerningDictForDirection_(self, direction: int) -> dict: ...
	def setKerningForFontMasterID_LeftKey_RightKey_Value_direction_(self, masterId: str, leftKey: str, rigthKey: str, value: float, direction: int) -> None: ...  # Glyphs 3
	def setKerningForFontMasterID_leftKey_rightKey_value_direction_(self, masterId: str, leftKey: str, rigthKey: str, value: float, direction: int) -> None: ...  # Glyphs 4
	@property
	def userData(self) -> dict: ...
	@property
	def tempData(self) -> Any: ...
	disablesNiceNames: bool
	customParameters: OrderedDictProxy["GSCustomParameter"]
	def customParameterForKey_(self, key: str) -> "GSCustomParameter": ...
	grid: int
	gridSubDivisions: int
	gridSubDivision: int
	@property
	def gridLength(self) -> int: ...
	disablesAutomaticAlignment: bool
	keyboardIncrement: int
	keyboardIncrementBig: int
	keyboardIncrementHuge: int
	snapToObjects: bool
	previewRemoveOverlap: int
	selection: list["GSGlyph"]
	@property
	def selectedLayers(self) -> list["GSLayer"]: ...
	@property
	def selectedFontMaster(self) -> "GSFontMaster": ...
	masterIndex: int
	currentText: str
	@property
	def tabs(self) -> list: ...
	@property
	def fontView(self) -> "GSFontViewController": ...
	currentTab: "GSEditViewController"
	@property
	def filepath(self) -> NSString: ...
	toolIndex: int
	tool: Any
	@property
	def tools(self) -> list: ...
	@property
	def appVersion(self) -> str: ...
	formatVersion: int
	@property
	def displayStrings(self) -> list[str]: ...
	def save(self, path: Optional[str] = None, formatVersion: Optional[int] = None, makeCopy: Optional[bool] = False) -> None: ...
	def close(self, ignoreChanges: Optional[bool] = True) -> None: ...
	def show(self) -> None: ...
	def kerningForPair(self, FontMasterID: str, LeftKerningId: str, RightKerningId: str, direction: Optional[int] = 0) -> Optional[float]: ...
	def setKerningForPair(self, FontMasterID: str, LeftKerningId: str, RightKerningId: str, Value: float, direction: Optional[int] = 0) -> Any: ...
	def removeKerningForPair(self, FontMasterID: str, LeftKerningId: str, RightKerningId: str, direction: Optional[int] = 0) -> Any: ...
	def newTab(self, tabText: Optional[str] = "") -> "GSEditViewController": ...
	def updateFeatures(self) -> Any: ...
	def compileFeatures(self) -> Any: ...
	def export(
		self,
		format: Optional[str] = "OTF",
		instances: Optional[list["GSInstance"]] = None,
		fontPath: Optional[str] = None,
		autoHint: Optional[bool] = True,
		removeOverlap: Any = None,
		useSubroutines: Optional[bool] = True,
		useProductionNames: Optional[bool] = True,
		containers: Any = None,
		decomposeSmartStuff: Optional[bool] = True
	) -> Any: ...

	# !! added manually
	def disableUpdateInterface(self) -> None: ...
	def enableUpdateInterface(self) -> None: ...

	def fontMasterAtIndex_(self, idx: int) -> "GSFontMaster": ...


class GSFontMaster(NSObject):
	id: str
	font: GSFont
	name: str
	iconName: str
	axes: OrderedDictProxy[int]
	metrics: OrderedDictProxy["GSMetricStore"]
	def valueForMetric_(self, metric: "GSMetric") -> "GSMetricStore": ...
	internalAxesValues: OrderedDictProxy[int]
	externalAxesValues: OrderedDictProxy[int]
	properties: OrderedDictProxy
	@property
	def metricValues(self) -> Any: ...
	ascender: float
	capHeight: float
	xHeight: float
	descender: float
	italicAngle: float
	stems: Any
	numbers: Any
	@property
	def alignmentZones(self) -> Any: ...
	@property
	def blueValues(self) -> Any: ...
	@property
	def otherBlues(self) -> Any: ...
	guides: List["GSGuide"]
	guideLines: List["GSGuide"]
	@property
	def userData(self) -> dict: ...
	customParameters: OrderedDictProxy["GSCustomParameter"]

	# !!
	def topHeightForLayer_(self, layer: "GSLayer") -> float: ...


class GSAxis(NSObject):
	@property
	def font(self) -> GSFont: ...
	name: str
	axisTag: str
	axisId: str
	id: str
	hidden: bool


class GSMetric(NSObject):
	@property
	def font(self) -> GSFont: ...
	name: str | None
	def typeName(self) -> str: ...
	@property
	def id(self) -> str: ...
	@property
	def title(self) -> str: ...
	type: int
	filter: Any
	horizontal: bool
	def isDefaultType(self) -> bool: ...


# class GlyphLayerProxy:

class GSGlyph(NSObject):
	def __init__(self, name: Optional[str] = None, autoName: Optional[bool] = True) -> None: ...
	parent: GSFont
	font: GSFont
	layers: OrderedDictProxy["GSLayer"]
	name: str
	unicode: str
	unicodes: list[str]
	def unicodeChar(self) -> int: ...
	axes: list[GSAxis]
	production: str
	string: str
	id: str
	locked: bool
	category: str
	storeCategory: bool
	subCategory: str
	storeSubCategory: bool
	case: int
	storeCase: bool
	direction: int
	storeDirection: bool
	script: str
	storeScript: bool
	productionName: Optional[str]
	storeProductionName: bool
	tags: list[str]
	glyphInfo: "GSGlyphInfo"
	sortName: str
	sortNameKeep: str
	storeSortName: bool
	def glyphId(self) -> int: ...
	def glyphDataEntryString(self) -> str: ...
	leftKerningGroup: str | None
	def setLeftKerningGroup_(self, value: str | None) -> None: ...
	rightKerningGroup: str
	def setRightKerningGroup_(self, value: str | None) -> None: ...
	topKerningGroup: str
	bottomKerningGroup: str
	@property
	def leftKerningKey(self) -> str: ...
	def leftKerningGroupId(self) -> str | None: ...
	@property
	def rightKerningKey(self) -> str: ...
	def rightKerningGroupId(self) -> str | None: ...
	@property
	def topKerningKey(self) -> str: ...
	@property
	def bottomKerningKey(self) -> str: ...
	leftMetricsKey: str
	def setLeftMetricsKey_(self, key: str | None) -> None: ...
	rightMetricsKey: str
	def setRightMetricsKey_(self, key: str | None) -> None: ...
	widthMetricsKey: str
	def setWidthMetricsKey_(self, key: str | None) -> None: ...
	export: bool
	color: int | None
	@property
	def colorObject(self) -> NSColor | None: ...
	@colorObject.setter
	def colorObject(self, value: NSColor | tuple | None) -> None: ...
	note: str | None
	selected: bool
	@property
	def mastersCompatible(self) -> bool: ...
	@property
	def userData(self) -> dict: ...
	@property
	@deprecated("Use .axes instead.")
	def smartComponentAxes(self) -> OrderedDictProxy["GSSmartComponentAxis"]: ...
	@property
	def lastChange(self) -> datetime.datetime: ...
	def beginUndo(self) -> None: ...
	def endUndo(self) -> None: ...
	def updateGlyphInfo(self, changeName: Optional[bool] = True) -> None: ...
	def duplicate(self, name: Optional[str] = None) -> "GSGlyph": ...
	def initLock(self) -> None: ...

	def layerForId_(self, layerId: str) -> "GSLayer" | None: ...
	def mastersCompatibleForLayerIds_(self, layerIds: list[str]) -> bool: ...


class GSGlyphsInfo(NSObject):

	@classmethod
	def customFontParameters(cls) -> list[str]: ...
	@classmethod
	def customMasterParameters(cls) -> list[str]: ...
	@classmethod
	def customInstanceParameters(cls) -> list[str]: ...
	@classmethod
	def sharedManager(cls) -> "GSGlyphsInfo": ...
	# @classmethod
	# def applicationSupportFolder(cls) -> str: ...
	@classmethod
	def applicationSupportPath(cls) -> str: ...
	@classmethod
	def addDescription_forParameter_(cls, desc: str, parameterName: str) -> None: ...
	@classmethod
	def addType_forParameter_forClass_(cls, aType: Any, parameterName: str, aClass: type) -> None: ...
class GSGlyphInfo(NSObject):
	@property
	def name(self) -> str: ...
	@property
	def productionName(self) -> str: ...
	@property
	def category(self) -> str: ...
	@property
	def subCategory(self) -> str: ...
	@property
	def case(self) -> Any: ...
	@property
	def components(self) -> list[str]: ...
	@property
	def accents(self) -> list[str]: ...
	@property
	def anchors(self) -> list[str]: ...
	@property
	def unicode(self) -> str: ...
	@property
	def unicodes(self) -> Any: ...
	@property
	def script(self) -> str: ...
	@property
	def index(self) -> Any: ...
	@property
	def sortName(self) -> str: ...
	@property
	def sortNameKeep(self) -> str: ...
	@property
	def desc(self) -> str: ...
	@property
	def altNames(self) -> Any: ...
	@property
	def direction(self) -> int: ...

	# !! added manually
	def unicharString(self) -> str: ...


class GSElement(NSObject):
	x: float
	y: float
	position: NSPoint
	@property
	def layer(self) -> "GSLayer": ...
	@property
	def glyph(self) -> "GSGlyph": ...
	@property
	def selected(self) -> bool: ...
	@selected.setter
	def selected(self, value: bool) -> None: ...


class GSGuide(GSElement):
	lockAngle: bool
	angle: float
	name: str
	locked: bool
	filter: NSPredicate
	showMeasurement: bool
	@property
	def userData(self) -> dict: ...


class GSHint(NSObject):
	@property
	def parent(self) -> "GSLayer": ...
	scale: NSPoint
	originNode: "GSNode"
	position: float
	width: float
	@property
	def origin(self) -> list[int]: ...
	@property
	def target(self) -> list[int]: ...
	@property
	def other1(self) -> list[int]: ...
	@property
	def other2(self) -> list[int]: ...
	targetNode: "GSNode" | "GSHandle" | None
	otherNode1: "GSNode" | "GSHandle" | None
	otherNode2: "GSNode" | "GSHandle" | None
	originIndex: list[int] | None
	targetIndex: list[int] | None
	otherIndex1: list[int] | None
	otherIndex2: list[int] | None
	type: int
	options: int
	def setOptions_(self, value: int) -> None: ...
	horizontal: bool
	name: str
	stem: int
	@property
	def isTrueType(self) -> bool: ...
	@property
	def isPostScript(self) -> bool: ...
	@property
	def isCorner(self) -> bool: ...
	@property
	def tempData(self) -> bool: ...
	alignment: int


class GSInstance(NSObject):
	active: bool
	exports: bool
	visible: bool
	name: str
	@property
	def type(self) -> int: ...
	def typeName(self) -> str: ...
	weightClass: int
	@property
	def weightClassName(self) -> str: ...
	widthClass: int
	@property
	def widthClassName(self) -> str: ...
	axes: List[float]
	internalAxesValues: List[float]
	externalAxesValues: List[float]
	properties: list["GSInfoValueSingle" | "GSInfoValueLocalized"]
	isItalic: bool
	isBold: bool
	linkStyle: str
	preferredFamily: str
	windowsFamily: str
	windowsStyle: str
	@property
	def windowsLinkedToStyle(self) -> str: ...
	fontName: str
	fullName: str
	compatibleFullName: str | None
	@property
	def compatibleFullNames(self) -> dict[str, str]: ...
	copyright: str | None
	@property
	def copyrights(self) -> dict[str, str]: ...
	description: str | None
	@property
	def descriptions(self) -> dict[str, str]: ...
	designer: str | None
	designerURL: str | None
	@property
	def designers(self) -> dict[str, str]: ...
	familyName: str | None
	@property
	def familyNames(self) -> dict[str, str]: ...
	license: str | None
	@property
	def licenses(self) -> dict[str, str]: ...
	manufacturer: str | None
	@property
	def manufacturers(self) -> dict[str, str]: ...
	preferredFamilyName: str | None
	@property
	def preferredFamilyNames(self) -> dict[str, str]: ...
	preferredSubfamilyName: str | None
	@property
	def preferredSubfamilyNames(self) -> dict[str, str]: ...
	sampleText: str | None
	@property
	def sampleTexts(self) -> dict[str, str]: ...
	styleMapFamilyName: str | None
	@property
	def styleMapFamilyNames(self) -> dict[str, str]: ...
	styleMapStyleName: str | None
	@property
	def styleMapStyleNames(self) -> dict[str, str]: ...
	styleName: str | None
	@property
	def styleNames(self) -> Any: ...
	trademark: str | None
	@property
	def trademarks(self) -> Any: ...
	variableStyleName: str | None
	@property
	def variableStyleNames(self) -> Any: ...
	manufacturerURL: str | None
	font: "GSFont"
	customParameters: OrderedDictProxy["GSCustomParameter"]
	def customParameterForKey_(self, key: str) -> "GSCustomParameter": ...
	@property
	def userData(self) -> dict: ...
	@property
	def tempData(self) -> dict: ...
	instanceInterpolations: dict
	manualInterpolation: bool
	@property
	def interpolatedFontProxy(self) -> "GSFont": ...
	@property
	def interpolatedFont(self) -> "GSFont": ...

	def generate(
		self,
		format: str = CFF,
		fontPath: Optional[str] = None,
		autoHint: bool = True,
		removeOverlap: bool = True,
		useSubroutines: bool = True,
		useProductionNames: bool = True,
		containers: Optional[list] = None,
		decomposeSmartStuff: bool = True
	) -> Optional[str]: ...
	lastExportedFilePath: Optional[str]
	def addAsMaster(self) -> GSFontMaster: ...
	def fileName(self, format: str) -> str: ...


class GSLayer(NSObject):
	parent: GSGlyph
	def glyph(self) -> GSGlyph: ...
	def font(self) -> GSFont: ...
	name: str
	@property
	def master(self) -> GSFontMaster: ...
	associatedMasterId: str
	def associatedFontMaster(self) -> GSFontMaster: ...
	layerId: str
	@property
	def attributes(self) -> dict[str, Any]: ...
	color: int | None
	colorObject: NSColor | None
	@property
	def components(self) -> list["GSComponent"]: ...
	guides: list[GSGuide]
	annotations: list["GSAnnotation"]
	hints: list[GSHint]
	anchors: DictProxy["GSAnchor"]
	shapes: list["GSShape"]
	@property
	def paths(self) -> list["GSPath"]: ...
	def segments(self) -> list["GSPathSegment"]: ...
	@property
	def selection(self) -> NSOrderedSet: ...
	@selection.setter
	def selection(self, selection: list | NSOrderedSet | None) -> None: ...
	LSB: float
	RSB: float
	TSB: float
	BSB: float
	width: float
	vertWidth: float
	vertOrigin: float
	def glyphMetrics(self) -> GSGlyphMetrics: ...
	@property
	def ascender(self) -> float: ...
	@property
	def descender(self) -> float: ...
	leftMetricsKey: str
	def setLeftMetricsKey_(self, key: str | None) -> None: ...
	def leftMetricsKeyUI(self) -> str: ...
	rightMetricsKey: str
	def setRightMetricsKey_(self, key: str | None) -> None: ...
	def rightMetricsKeyUI(self) -> str: ...
	widthMetricsKey: str
	def setWidthMetricsKey_(self, key: str | None) -> None: ...
	def widthMetricsKeyUI(self) -> str: ...
	def metricsKeysOutOfSync(self) -> bool: ...
	@property
	def bounds(self) -> NSRect: ...
	@property
	def selectionBounds(self) -> NSRect: ...
	@property
	def metrics(self) -> Any: ...
	@property
	def background(self) -> "GSLayer": ...
	@background.setter
	def background(self, value: "GSLayer" | None) -> None: ...
	backgroundImage: "GSBackgroundImage" | None
	@property
	def bezierPath(self) -> NSBezierPath: ...
	@property
	def openBezierPath(self) -> NSBezierPath: ...
	@property
	def drawBezierPath(self) -> NSBezierPath: ...
	@property
	def completeBezierPath(self) -> NSBezierPath: ...
	@property
	def drawOpenBezierPath(self) -> NSBezierPath: ...
	@property
	def completeOpenBezierPath(self) -> NSBezierPath: ...
	@property
	def isAligned(self) -> bool: ...
	@property
	def isSpecialLayer(self) -> bool: ...
	@property
	def isMasterLayer(self) -> bool: ...
	@property
	def italicAngle(self) -> float: ...
	visible: bool
	@property
	def userData(self) -> dict: ...
	@property
	def tempData(self) -> dict: ...
	@property
	def smartComponentPoleMapping(self) -> dict: ...
	def removeOverlap(self, checkSelection: Optional[bool] = False) -> None: ...
	def addNodesAtExtremes(self, force: Optional[bool] = False, checkSelection: Optional[bool] = False) -> None: ...
	def applyTransform(self, transformStruct: NSAffineTransformStruct | tuple[float, float, float, float, float, float]) -> None: ...
	def transform(self, transform: NSAffineTransform, selection: Optional[bool] = False, components: Optional[bool] = True) -> None: ...
	def beginChanges(self) -> Any: ...
	def endChanges(self) -> Any: ...
	def cutBetweenPoints(self, point1: NSPoint, point2: NSPoint) -> Any: ...
	def intersectionsBetweenPoints(self, point1: NSPoint, point2: NSPoint, components: Optional[bool] = False, ignoreLocked: Optional[bool] = False) -> Any: ...
	def calculateIntersectionsStartPoint_endPoint_decompose_(self, point1: NSPoint | tuple[float, float], point2: NSPoint | tuple[float, float], decompose: bool) -> list: ...
	def addMissingAnchors(self) -> Any: ...
	def reinterpolate(self) -> Any: ...
	def draw(self, pen: Any, contours: Optional[bool] = True, components: Optional[bool] = True) -> Any: ...
	def drawPoints(self, pen: Any, contours: Optional[bool] = True, components: Optional[bool] = True) -> Any: ...
	def getPen(self) -> Any: ...
	def getPointPen(self) -> Any: ...
	# !!

	def updateMetrics(self): ...
	def swapForegroundWithBackground(self): ...
	def decomposeComponents(self): ...
	def transform_checkForSelection_doComponents_(self, transform: Union[NSAffineTransform, NSAffineTransformStruct, tuple], checkForSelection: bool, doComponents: bool) -> None: ...

	def drawInFrame_(self, frame: NSRect) -> None: ...
	def drawInFrame_metrics_color_dark_(self, frame: NSRect, metrics: GSGlyphMetrics, color: NSColor, dark: bool) -> None: ...
	def copyDecomposedLayer(self) -> "GSLayer": ...
	def compareString(self) -> str: ...
	def decomposeCorners(self) -> None: ...
	def flattenOutlines(self) -> bool: ...
	def connectAllOpenPaths(self) -> None: ...
	def syncMetrics(self) -> None: ...
	def correctPathDirection(self) -> None: ...
	def roundCoordinates(self) -> None: ...
	def clear(self) -> None: ...
	def cleanUpPaths(self) -> None: ...
	def nodeAtPoint_excludeNode_ignoreLocked_tolerance_(self, point: NSPoint, exclude: "GSNode" | None, ignoreLocked: bool, tolerance: float) -> "GSNode": ...

class GSHandle(NSObject):
	flag: int
	cursor: NSCursor
	object: Any
	position: NSPoint

	canAttachHint: bool
	canAttachCorner: bool


class GSNode(GSElement):
	def __init__(self, pt: Optional[NSPoint] = None, type: Optional[int | str] = None, x: Optional[float] = None, y: Optional[float] = None, name: Optional[str] = None, pointType: Optional[int] = None) -> None: ...
	parent: "GSPath" | None
	type: str | int
	smooth: int
	connection: int
	@property
	def layer(self) -> GSLayer: ...
	@property
	def index(self) -> int: ...
	@property
	def nextNode(self) -> "GSNode": ...
	@property
	def prevNode(self) -> "GSNode": ...
	name: str
	@property
	def attributes(self) -> dict[str, Any]: ...
	@property
	def userData(self) -> dict[str, Any]: ...

	# !!
	x: float
	y: float

class GSShape(NSObject):
	parent: GSLayer
	locked: bool
	userData: DictProxy
	@property
	def selected(self) -> bool: ...
	@selected.setter
	def selected(self, value: bool) -> None: ...
	def setUserData_forKey_(self, data: Any, key: str) -> None: ...


class GSPath(GSShape):
	locked: bool
	@property
	def shapeType(self) -> Any: ...
	parent: GSLayer
	nodes: list[GSNode]
	segments: list["GSPathSegment"]
	closed: bool
	@property
	def direction(self) -> int: ...
	@property
	def bounds(self) -> NSRect: ...
	@property
	def bezierPath(self) -> NSBezierPath: ...
	@property
	def attributes(self) -> dict: ...
	@property
	def tempData(self) -> dict: ...
	def draw(self, pen: Any) -> None: ...
	def drawPoints(self, pen: Any) -> None: ...
	def addNodesAtExtremes(self, force: Optional[bool] = False, checkSelection: Optional[bool] = False) -> None: ...
	def applyTransform(self, transformStruct: NSAffineTransformStruct) -> None: ...
	def reverse(self) -> None: ...
	def insertNodeWithPathTime_(self, time: float) -> GSNode: ...
	def unitVectorAtNodeAtIndex_(self, idx: int) -> NSPoint: ...
	def indexOfNode_(self, node: GSNode) -> int: ...
	def area(self) -> float: ...


class GSAlignmentZone(NSObject):
	position: float
	size: float
	def plistValue(self) -> dict: ...


class GSAnchor(GSElement):
	def __init__(self, name: Optional[str] = None, pt: Optional[NSPoint | tuple] = None) -> None: ...
	position: NSPoint
	name: str
	@property
	def userData(self) -> dict: ...
	def draw(self, pen: Any) -> Any: ...
	def drawPoints(self, pen: Any) -> Any: ...


class GSAnnotation(NSObject):
	position: NSPoint
	type: int
	text: str
	angle: float
	width: float


class classproperty:
	def __init__(self, fget):
		self.fget = fget

	def __get__(self, obj, owner):
		# owner is the class on which it’s accessed
		return self.fget(owner)


class GSApplication(NSApplication):
	def isActive(self) -> bool: ...
	@property
	def currentDocument(self) -> Any: ...
	@property
	def documents(self) -> Any: ...
	@property
	def font(self) -> GSFont: ...
	@property
	def fonts(self) -> List[GSFont]: ...

	reporters: list

	@property
	def activeReporters(self) -> list: ...
	@property
	def filters(self) -> list: ...
	@classproperty
	def defaults(self) -> dict: ...
	def registerDefault(self, key: str, value: Any) -> Any: ...
	def registerDefaults(self, defaults: Any) -> Any: ...
	@classproperty
	def boolDefaults(self) -> Any: ...
	@classproperty
	def colorDefaults(self) -> Any: ...
	@classproperty
	def intDefaults(self) -> Any: ...
	@classproperty
	def floatDefaults(self) -> Any: ...
	@classproperty
	def scriptAbbreviations(self) -> dict[str, str]: ...
	@classproperty
	def scriptSuffixes(self) -> dict[str, str]: ...
	@property
	def languageScripts(self) -> dict[str, str]: ...
	@property
	def languageData(self) -> list[dict]: ...
	@property
	def unicodeRanges(self) -> list[str]: ...
	editViewWidth: Any
	handleSize: Any
	@property
	def versionString(self) -> str: ...
	@property
	def versionNumber(self) -> float: ...
	@property
	def buildNumber(self) -> float: ...
	@property
	def menu(self) -> Any: ...
	def open(self, path: Any, showInterface: Optional[bool] = True) -> Any: ...
	@classmethod
	def showMacroWindow(cls) -> Any: ...
	def showGlyphInfoPanelWithSearchString(self, String: Any) -> Any: ...
	def glyphInfoForName(self, name: str, font: Optional[GSFont] = None) -> GSGlyphInfo: ...
	def glyphInfoForUnicode(self, string: str, font: Optional[GSFont] = None) -> GSGlyphInfo: ...
	def niceGlyphName(self, name: str, font: Optional[GSFont] = None) -> str: ...
	def productionGlyphName(self, name: str, font: Optional[GSFont] = None) -> str: ...
	def ligatureComponents(self, name: str, font: Optional[GSFont] = None) -> list[str] | None: ...
	def addCallback(self, target: Any = None, operation: Any = None, callbackType: Any = None, callee: Any = None, selector: Any = None) -> Any: ...
	def removeCallback(self, target: Any = None, operation: Any = None, callbackType: Any = None, callee: Any = None) -> Any: ...
	def redraw(self) -> Any: ...
	def showNotification(self, title: str, message: str) -> Any: ...
	def localize(self, localization: Dict[str, str]) -> str: ...
	def activateReporter(self, reporter: Any) -> Any: ...
	def deactivateReporter(self, reporter: Any) -> Any: ...
	currentFontDocument: Any

	# !! manually added
	def clearLog(self) -> None: ...
	def orderedDocuments(self) -> List["GSFont" | "GSProjectDocument"]: ...
	def delegate(self) -> Any: ...
	@classmethod
	def showAlert_message_OKButton_(cls, title: str, message: str, OKButton: str | None) -> None: ...

class GSImage(NSObject):
	def __init__(self, path: Optional[str] = None) -> None: ...
	path: str
	@property
	def image(self) -> NSImage: ...
	crop: NSRect
	locked: bool
	alpha: float
	position: NSPoint
	scale: NSPoint
	rotation: float
	transform: NSAffineTransform
	def resetCrop(self) -> Any: ...
	def scaleWidthToEmUnits(self, value: Any) -> Any: ...
	def scaleHeightToEmUnits(self, value: Any) -> Any: ...


class GSBackgroundImage(GSImage):
	...


class GSBackgroundLayer(GSLayer):
	parent: Any
	name: str
	associatedMasterId: str
	width: float


class GSClass(NSObject):
	@property
	def parent(self) -> "GSFont": ...
	name: str
	code: str
	automatic: bool
	active: bool
	@property
	def tempData(self) -> Dict: ...
	def __init__(self, name: Optional[str] = None, code: Optional[str] = None) -> None: ...

class GSComponent(GSShape):
	def __init__(self, glyph: Optional[str | GSGlyph] = None, offset: Optional[tuple] = (0, 0), scale: Optional[tuple] = (1, 1), transform: Optional[tuple] = None): ...
	position: NSPoint
	x: float
	y: float
	scale: NSPoint | tuple
	rotation: float
	componentName: str
	name: str
	componentMasterId: str
	@property
	def component(self) -> Optional[GSGlyph]: ...
	@property
	def componentLayer(self) -> Optional[GSLayer]: ...
	transform: NSAffineTransformStruct | tuple
	@property
	def bounds(self) -> NSRect: ...
	disableAlignment: bool
	automaticAlignment: bool
	alignment: int
	locked: bool
	anchor: str
	traverseAnchors: bool
	@property
	def attributes(self) -> dict: ...
	def draw(self, pen: Any) -> Any: ...
	def drawPoints(self, pen: Any) -> Any: ...
	@property
	def smartComponentValues(self) -> Any: ...
	@property
	def bezierPath(self) -> Any: ...
	@property
	def tempData(self) -> Any: ...
	parent: Any
	def decompose(self, doAnchors: Optional[bool] = True, doHints: Optional[bool] = True) -> Any: ...
	def applyTransform(self, transformStruct: Any) -> Any: ...
	@property
	def shapeType(self) -> Any: ...


class GSControlLayer(NSObject):
	def __new__(cls: type["GSControlLayer"], char: int) -> "GSControlLayer": ...
	@property
	def parent(self) -> Any: ...
	@classmethod
	def newline(cls) -> Self: ...
	@classmethod
	def placeholder(cls) -> Self: ...

class GSParameterValueViewController(NSViewController):
	...

class GSPropertyDialogController(NSWindowController):
	...

class GSCustomParameter(NSObject):
	def __init__(self, name: str, value: Any) -> None: ...
	name: str
	value: Any
	active: bool
	@property
	def parent(self) -> Any: ...

	@classmethod
	def registerCustomType(
		cls,
		parameterName: str,
		parameterType: str | None = None,
		listUIClass: Type[GSParameterValueViewController] | str | None = None,
		dialogUIClass: Type[GSPropertyDialogController] | str | None = None
	) -> None: ...


class GSDocument(NSDocument):
	font: GSFont
	@property
	def filePath(self) -> str: ...
	selectedLayers: List[GSLayer]
	def presentError_(self, error: NSError) -> None: ...
	def windowController(self) -> "GSWindowController": ...

class GSProjectDocument(NSDocument):
	font: GSFont
	instances: List[GSInstance]

	# !! added manually
	def exportPath(self) -> str: ...


class GSLayoutManager(NSObject):
	def cachedLayers(self) -> list[GSLayer]: ...


class GSGlyphEditView(NSView):
	def scale(self) -> float: ...
	def setScale_(self, scale: float) -> None: ...
	def activeLayer(self) -> GSLayer: ...
	def activePosition(self) -> NSPoint: ...
	def setDoSpacing_(self, value: bool) -> None: ...
	def setDoKerning_(self, value: bool) -> None: ...
	def setKerningMode_(self, value: bool) -> None: ...
	def selectedRange(self) -> NSRange: ...
	def drawDark(self) -> bool: ...
	def selectedLayerRange(self) -> NSRange: ...
	def textStorage(self) -> NSTextStorage: ...
	def cachedPositionAtIndex_(self, idx: int) -> NSPoint: ...
	def layerIndexForPoint_(self, point: NSPoint) -> int: ...
	def cachedLayerCount(self) -> int: ...
	def layoutManager(self) -> GSLayoutManager: ...
	def drawLayer_atPoint_asActive_attributes_(self, layer: GSLayer, point: NSPoint, active: bool, attibutes: dict) -> None: ...
	def getActiveLocation_(self, event: NSEvent) -> NSPoint: ...

class GSWindowController(NSWindowController):
	def toolDrawDelegate(self) -> Any: ...
	def activeEditViewController(self) -> "GSEditViewController": ...
	def masterIndex(self) -> int: ...
	def toolTempSelection(self) -> Any | None: ...
	def toolEventHandler(self) -> Any: ...
	def document(self) -> GSDocument: ...
	def ShiftKey(self) -> bool: ...
	def AltKey(self) -> bool: ...
	def CtrlKey(self) -> bool: ...
	def CommandKey(self) -> bool: ...
	def SpaceKey(self) -> bool: ...
	def setToolForClass_(self, cls: Any) -> None: ...
	def showFontInfoWindowWithTabSelected_(self, idx: int) -> NSViewController: ...
	def fontInfoWindowController(self) -> NSWindowController: ...  # GSInfoWindowController


class GSEditViewController(NSViewController):
	@property
	def parent(self) -> Any: ...
	def windowController(self) -> GSWindowController: ...
	text: str
	string: str
	masterIndex: int
	def activeLayer(self) -> GSLayer: ...
	@property
	def selectedLayers(self) -> List[GSLayer]: ...
	layers: List[GSLayer]
	@property
	def composedLayers(self) -> List[GSLayer]: ...
	def shadowLayer(self) -> GSLayer: ...
	def setShadowLayer_(self, layer: GSLayer) -> None: ...
	scale: float
	def forceRedraw(self) -> None: ...
	viewPort: NSRect
	@property
	def safeViewPort(self) -> NSRect: ...
	@property
	def bounds(self) -> NSRect: ...
	@property
	def selectedLayerOrigin(self) -> NSPoint: ...
	textCursor: int
	textRange: NSRange
	layersCursor: int
	direction: int
	features: list
	@property
	def tempData(self) -> dict: ...
	previewInstances: Any
	previewHeight: Any
	@property
	def bottomToolbarHeight(self) -> Any: ...
	close: Any
	def saveToPDF(self, path: Any, rect: Any = None) -> Any: ...

	def graphicView(self) -> GSGlyphEditView: ...
	def infoView(self) -> NSStackView: ...
	def redraw(self) -> None: ...
	# !!
	def initialZoom(self) -> None: ...


class GSFontViewController(NSViewController):
	@property
	def parent(self) -> Any: ...
	@property
	def selectedLayers(self) -> List[GSLayer]: ...
	def glyphsArrayController(self) -> NSArrayController: ...

class GSGradient(NSObject):
	colors: Any
	type: Any
	start: Any
	end: Any
	absoluteStart: Any
	absoluteEnd: Any


class GSFeature(NSObject):
	@property
	def parent(self) -> "GSFont": ...
	name: str
	code: str
	automatic: bool
	notes: str
	active: bool
	labels: list
	def __init__(self, name: Optional[str] = None, code: Optional[str] = None) -> None: ...
	@property
	def tempData(self) -> dict: ...
	def update(self) -> None: ...


class GSFeaturePrefix(NSObject):
	@property
	def parent(self) -> "GSFont": ...
	name: str
	code: str
	automatic: bool
	active: bool
	def __init__(self, name: Optional[str] = None, code: Optional[str] = None) -> None: ...


class GSProxyShapes(NSObject):
	def append(self, item: Any) -> Any: ...
	def extend(self, items: Any) -> Any: ...


class GSSubstitution(NSObject):
	back: Any
	source: Any
	forward: Any
	target: Any
	languageTag: Any
	scriptTag: Any


class GSPartProperty(NSObject):
	name: Any
	@property
	def id(self) -> Any: ...
	topValue: Any
	bottomValue: Any


class GSNotifyingDictionary(NSDictionary):
	def items(self) -> Any: ...
	def keys(self) -> Any: ...


class GSPathPen(NSObject):
	def beginPath(self, identifier: Any, kwargs: Any) -> Any: ...
	def moveTo(self, pt: Any) -> Any: ...
	def lineTo(self, pt: Any) -> Any: ...
	def curveTo(self, off1: Any, off2: Any, pt: Any) -> Any: ...
	def addPoint(self, pt: Any, segmentType: Any = None, smooth: Optional[bool] = False, name: Any = None, identifier: Any = None) -> Any: ...


class GSInterpolationFontProxy(GSFont):
	@property
	def masters(self) -> Any: ...
	glyphs: list[GSGlyph]


class GSTTStem(NSObject):
	def plistValue(self) -> dict: ...


class GSMacroViewController(NSViewController):
	title: Any


class GSPathFinder(NSObject):
	@classmethod
	def addIntersections_(cls, segments: list["GSPathSegment"] | NSMutableArray["GSPathSegment"]) -> bool: ...


class GSPathSegment(NSObject):
	@property
	def bounds(self) -> Any: ...
	@property
	def type(self) -> Any: ...
	def initWithDescription_(self, desc: str) -> Self: ...
	def initWithCurvePoint1_point2_point3_point4_options_(self, p1: NSPoint, p2: NSPoint, p3: NSPoint, p4: NSPoint, options: int) -> Self: ...
	def length(self) -> float: ...

class GSInfoValueLocalized(NSObject):
	key: Any
	values: Any
	@property
	def defaultValue(self) -> Any: ...


class GSInfoValueSingle(NSObject):
	key: str
	value: str


class GSInfoValue(NSObject):
	key: str
	value: Any
	languageTag: str


class GSMetricStore(NSObject):
	position: float
	overshoot: float
	size: float
	@property
	def name(self) -> str: ...
	@property
	def filter(self) -> NSPredicate | None: ...
	@property
	def metric(self) -> GSMetric: ...


class GSTransformableElement(NSObject):
	@property
	def userData(self) -> dict: ...


Glyphs = GSApplication()


class GSCallbackHandler:

	def reporterInstances(self) -> list: ...
	@classmethod
	def addCallback_forOperation_(cls, target: Any, operation: str) -> None: ...
	@classmethod
	def removeCallback_forOperation_(cls, target: Any, operation: str) -> None: ...
	@classmethod
	def addFeatureCodeGenerator_(cls, target: Any) -> None: ...

class callbackHelperClass:
	pass

class GSGlyphReference(NSObject):
	def __init__(self, glyph: GSGlyph) -> None: ...
	glyph: GSGlyph


def Message(message: str, title: Optional[str] = "Alert", OKButton: Optional[str] = None): ...

def AskString(message: str, value: Optional[str] = None, title: str = "Glyphs", OKButton: Optional[str] = None, placeholder: Optional[str] = None) -> str: ...

def distance(P1: NSPoint, P2: NSPoint) -> float: ...


def addPoints(P1: NSPoint, P2: NSPoint) -> NSPoint: ...


def subtractPoints(P1: NSPoint, P2: NSPoint) -> NSPoint: ...


def scalePoint(P: NSPoint, scalar: float) -> NSPoint: ...


def LogToConsole(message: str, title: str | None = None): ...


def LogError(message: str): ...


class GSUserNotification(NSObject):

	"""The title of the notification. Must be localized as it will be presented to the user. String will be truncated to a length appropriate for display."""
	title: str | None

	"""The subtitle displayed in the notification. Must be localized as it will be presented to the user. String will be truncated to a length appropriate for display."""
	subtitle: str | None

	"""The body of the notification. Must be localized as it will be presented to the user. String will be truncated to a length appropriate for display."""
	informativeText: str | None

	"""The title of the button displayed in the notification. Must be localized as it will be presented to the user. String will be truncated to a length appropriate for display."""
	actionButtonTitle: str

	"""Application-specific user info that may be retrieved later. All items must be property list types or an exception will be thrown. The userInfo should be of reasonable serialized size or an exception will be thrown."""
	userInfo: dict | None

	def deliver(self) -> None: ...


class GSSmartComponentAxis(NSObject):
	name: str
	topValue: float
	bottomValue: float


class GlyphsToolOther(NSObject):
	@classmethod
	def cutPathsInLayer_forPoint_endPoint(cls, p1: NSPoint, p2: NSPoint) -> None: ...


class GSExportInstanceOperation(NSObject):
	def initWithFont_instance_outlineFormat_containers_(self, font: GSFont, instance: GSInstance, format: int, containerList: list[str]) -> Self: ...




def GetFile(message=None, title=None, allowsMultipleSelection: bool = False, filetypes=None) -> str | list | None: ...

def GetOpenFile(message: str | None = None, title: str | None = None, allowsMultipleSelection: bool = False, filetypes: list | None = None, path: str | None = None) -> str | list | None: ...

def GetSaveFile(message: Optional[str] = None, proposedFileName: Optional[str] = None, filetypes: Optional[List[str]] = None, filetype: Optional[str] = None) -> str | None: ...

def GetFolder(message: str | None = None, allowsMultipleSelection: bool = False, path: str | None = None) -> str | list | None: ...

INSTANCETYPESINGLE = 0
INSTANCETYPEVARIABLE = 1
GSNoCase = 0
GSUppercase = 1
GSLowercase = 2
GSSmallcaps = 3
GSMinor = 4

GSMOVE: str = "move"
GSLINE: str = "line"
GSCURVE: str = "curve"
GSQCURVE: str = "qcurve"
GSOFFCURVE: str = "offcurve"
GSHOBBYCURVE: str = "hobby"

GSSHARP = 0
GSSMOOTH = 100

TAG: int
TOPGHOST: int
STEM: int
BOTTOMGHOST: int
FLEX: int
TTSNAP: int
TTANCHOR: int  # backwards compatibility
TTSTEM: int
TTSHIFT: int
TTALIGN: int  # backwards compatibility
TTINTERPOLATE: int
TTDIAGONAL: int
TTDELTA: int
CORNER: int
CAP: int
BRUSH: int
SEGMENT: int

TTDONTROUND: int
TTROUND: int
TTROUNDUP: int
TTROUNDDOWN: int
TRIPLE: int


TEXT = 1
ARROW = 2
CIRCLE = 3
PLUS = 4
MINUS = 5

GSBIDI = 1
GSLTR = 0
GSRTL = 2
BIDI = 1
LTR = 0
RTL = 2
LTRTTB = 4
RTLTTB = 8
GSVertical = 4  # CJK
GSVerticalToRight = 8  # Mongolian

OTF = "OTF"
TTF = "TTF"
VARIABLE = "variable"
UFO = "UFO"
WOFF = "WOFF"
WOFF2 = "WOFF2"
PLAIN = "plain"
EOT = "EOT"

GSShapeTypePath: int = 1 << 1
GSShapeTypeComponent: int = 1 << 2


DRAWFOREGROUND: str
DRAWBACKGROUND: str
DRAWINACTIVE: str
DOCUMENTOPENED: str
DOCUMENTACTIVATED: str
DOCUMENTWASSAVED: str
DOCUMENTEXPORTED: str
DOCUMENTCLOSED: str
DOCUMENTWILLCLOSE: str
DOCUMENTDIDCLOSE: str
TABDIDOPEN: str
TABWILLCLOSE: str
UPDATEINTERFACE: str
UPDATEEDITVIEWFRAME: str
MOUSEMOVED: str
MOUSEDRAGGED: str
MOUSEDOWN: str
MOUSEUP: str
CONTEXTMENUCALLBACK: str
FILTER_FLAT_KERNING: str


APP_MENU: str
FILE_MENU: str
EDIT_MENU: str
GLYPH_MENU: str
PATH_MENU: str
FILTER_MENU: str
VIEW_MENU: str
SCRIPT_MENU: str
WINDOW_MENU: str
HELP_MENU: str


ONSTATE: int
OFFSTATE: int
MIXEDSTATE: int


def objcObject(pyObject: Any) -> NSObject: ...

def NSStr(str) -> NSString: ...

LINE: str
CURVE: str
OFFCURVE: str
