// generated by vicinae figura codegen - do not edit manually

interface JsonRpcMessage {
	jsonrpc: "2.0";
	method?: string;
	id?: number;
	params?: Record<string, any>;
	result?: any;
	error?: any;
}

interface ITransport {
	send(data: string): void;
}

type EventSubscription = {
	unsubscribe: () => void;
};

export class RpcTransport {
	constructor(private readonly transport: ITransport) {}

	dispatchMessage(data: string) {
		const msg = JSON.parse(data) as JsonRpcMessage;

		if (msg.id !== undefined) {
			const handler = this.requestMap.get(msg.id);

			if (handler) {
				if (msg.error) handler.reject(msg.error);
				else handler.resolve(msg.result);
				this.requestMap.delete(msg.id);
			}
		}
		if (msg.id === undefined && msg.method) {
			for (const cb of this.handlers.get(msg.method) ?? []) {
				cb(msg.params);
			}
		}
	}

	request<T>(method: string, params: Record<string, any>): Promise<T> {
		const id = this.id++;
		const promise = new Promise<T>((resolve, reject) => {
			this.requestMap.set(id, { resolve: (msg) => resolve(msg as T), reject });
		});

		this.sendMessage({ jsonrpc: "2.0", id, method, params });

		return promise;
	}

	subscribe(method: string, cb: (result: any) => void): EventSubscription {
		const handlers = this.handlers.get(method);

		if (handlers) handlers.push(cb);
		else this.handlers.set(method, [cb]);

		return {
			unsubscribe: () => {
				const handlers = this.handlers.get(method);

				if (handlers) {
					handlers.splice(handlers.indexOf(cb), 1);
				}
			},
		};
	}

	private sendMessage(msg: JsonRpcMessage) {
		this.transport.send(JSON.stringify(msg));
	}

	private id = 1;
	private requestMap = new Map<
		number,
		{ resolve: (value: any) => void; reject: (error: any) => void }
	>();
	private handlers = new Map<string, Array<(result: any) => void>>();
}

export type ImageMask = "None" | "Circle" | "RoundedRectangle";

export type ToastStyle = "Success" | "Info" | "Warning" | "Error" | "Dynamic";

export type PopToRootType = "Default" | "Immediate" | "Suspended";

export type ConfirmAlertActionStyle = "Default" | "Destructive" | "Cancel";

export type NotificationUrgency = "Low" | "Normal" | "High";

export type FileSearchCategory =
	| "Other"
	| "Directory"
	| "Image"
	| "Video"
	| "Audio"
	| "Document"
	| "Archive"
	| "Application";

export type Application = {
	id: string;
	name: string;
	icon?: string;
	path: string;
};

export type RunInTerminalPayload = {
	cmdline: string[];
	hold: boolean;
	appId?: string;
	workingDirectory?: string;
	title?: string;
};

export type ThemedImageSource = {
	light?: string;
	dark?: string;
};

export type ImageSource = {
	raw?: string;
	themed?: ThemedImageSource;
};

export type DynamicColor = {
	light: string;
	dark: string;
	adjustContrast?: boolean;
};

export type ColorLike = {
	raw?: string;
	dynamic?: DynamicColor;
};

export type Image = {
	source?: ImageSource;
	fallback?: ImageSource;
	mask?: ImageMask;
	tintColor?: ColorLike;
	fileIcon?: string;
};

export type ConfirmAlertAction = {
	title: string;
	style: ConfirmAlertActionStyle;
};

export type ConfirmAlertPayload = {
	title: string;
	description: string;
	primaryAction: ConfirmAlertAction;
	dismissAction: ConfirmAlertAction;
	rememberUserChoice: boolean;
	icon?: Image;
};

export type DesktopNotificationPayload = {
	title: string;
	body: string;
	icon?: Image;
	urgency: NotificationUrgency;
};

export type Rect = {
	x: number;
	y: number;
	width: number;
	height: number;
};

export type Window = {
	id: string;
	title: string;
	workspaceId: string;
	active: boolean;
	fullscreen: boolean;
	bounds: Rect;
	app?: Application;
};

export type Screen = {
	name: string;
	model: string;
	make: string;
	serial?: string;
	bounds: Rect;
};

export type Workspace = {
	id: string;
	name: string;
	active: boolean;
	fullscreen: boolean;
	monitor: string;
};

export type ClipboardContent = {
	text?: string;
	html?: string;
	path?: string;
};

export type ClipboardOptions = {
	concealed: boolean;
};

export type FileInfo = {
	path: string;
	category: FileSearchCategory;
	mimeType?: string;
};

export type FileSearchFilters = {
	category?: FileSearchCategory;
};

export type FileSearchOptions = {
	filters: FileSearchFilters;
	limit: number;
};

export type UpdateCommandMetadataPayload = {
	subtitle?: string;
};

export type PKCEClientOptions = {
	name: string;
	id?: string;
	description: string;
	icon?: Image;
};

export type AuthorizeRequest = {
	client: PKCEClientOptions;
	url: string;
};

export type AuthorizeResponse = {
	code: string;
};

export type TokenSet = {
	accessToken: string;
	refreshToken?: string;
	idToken?: string;
	expiresIn?: number;
	scope?: string;
	updatedAt: number;
};

export type SetTokensRequest = {
	providerId?: string;
	accessToken: string;
	refreshToken?: string;
	idToken?: string;
	expiresIn?: number;
	scope?: string;
};

export type TokenSetResponse = {
	set?: TokenSet;
};

class ApplicationService {
	constructor(private readonly transport: RpcTransport) {}

	list(target?: string): Promise<Application[]> {
		return this.transport.request("Application/list", { target });
	}

	open(target: string, appId?: string): Promise<void> {
		return this.transport.request("Application/open", { target, appId });
	}

	getDefault(target: string): Promise<Application> {
		return this.transport.request("Application/getDefault", { target });
	}

	showInFileBrowser(target: string, select: boolean): Promise<void> {
		return this.transport.request("Application/showInFileBrowser", {
			target,
			select,
		});
	}

	runInTerminal(opts: RunInTerminalPayload): Promise<boolean> {
		return this.transport.request("Application/runInTerminal", { opts });
	}
}

class UIService {
	constructor(private readonly transport: RpcTransport) {}

	render(json: string): Promise<void> {
		return this.transport.request("UI/render", { json });
	}

	showToast(
		id: string,
		title: string,
		message: string,
		style: ToastStyle,
	): Promise<void> {
		return this.transport.request("UI/showToast", {
			id,
			title,
			message,
			style,
		});
	}

	updateToast(id: string, title: string): Promise<void> {
		return this.transport.request("UI/updateToast", { id, title });
	}

	hideToast(id: string): Promise<void> {
		return this.transport.request("UI/hideToast", { id });
	}

	showHud(
		text: string,
		clear_root: boolean,
		popToRoot: PopToRootType,
	): Promise<void> {
		return this.transport.request("UI/showHud", {
			text,
			clear_root,
			popToRoot,
		});
	}

	closeMainWindow(clearRoot: boolean, popToRoot: PopToRootType): Promise<void> {
		return this.transport.request("UI/closeMainWindow", {
			clearRoot,
			popToRoot,
		});
	}

	popToRoot(clearSearchBar: boolean): Promise<void> {
		return this.transport.request("UI/popToRoot", { clearSearchBar });
	}

	confirmAlert(payload: ConfirmAlertPayload): Promise<boolean> {
		return this.transport.request("UI/confirmAlert", { payload });
	}

	pushView(): Promise<void> {
		return this.transport.request("UI/pushView", {});
	}

	popView(): Promise<void> {
		return this.transport.request("UI/popView", {});
	}

	setSearchText(text: string): Promise<void> {
		return this.transport.request("UI/setSearchText", { text });
	}

	getSelectedText(): Promise<string> {
		return this.transport.request("UI/getSelectedText", {});
	}

	sendDesktopNotification(data: DesktopNotificationPayload): Promise<void> {
		return this.transport.request("UI/sendDesktopNotification", { data });
	}

	viewPoped(handler: () => void): EventSubscription {
		return this.transport.subscribe("UI/viewPoped", (msg) => handler());
	}
	viewPushed(handler: () => void): EventSubscription {
		return this.transport.subscribe("UI/viewPushed", (msg) => handler());
	}
}

class WindowManagementService {
	constructor(private readonly transport: RpcTransport) {}

	focusWindow(winId: string): Promise<boolean> {
		return this.transport.request("WindowManagement/focusWindow", { winId });
	}

	getActiveWindow(): Promise<Window> {
		return this.transport.request("WindowManagement/getActiveWindow", {});
	}

	getActiveWorkspace(): Promise<Workspace> {
		return this.transport.request("WindowManagement/getActiveWorkspace", {});
	}

	getWindows(workspaceId?: string): Promise<Window[]> {
		return this.transport.request("WindowManagement/getWindows", {
			workspaceId,
		});
	}

	getScreens(): Promise<Screen[]> {
		return this.transport.request("WindowManagement/getScreens", {});
	}

	getWorkspaces(): Promise<Workspace[]> {
		return this.transport.request("WindowManagement/getWorkspaces", {});
	}

	setWindowBounds(winId: string, bounds: Rect): Promise<void> {
		return this.transport.request("WindowManagement/setWindowBounds", {
			winId,
			bounds,
		});
	}
}

class ClipboardService {
	constructor(private readonly transport: RpcTransport) {}

	copy(content: ClipboardContent, options: ClipboardOptions): Promise<void> {
		return this.transport.request("Clipboard/copy", { content, options });
	}

	paste(content: ClipboardContent): Promise<void> {
		return this.transport.request("Clipboard/paste", { content });
	}

	clear(): Promise<void> {
		return this.transport.request("Clipboard/clear", {});
	}

	readContent(): Promise<ClipboardContent> {
		return this.transport.request("Clipboard/readContent", {});
	}
}

class StorageService {
	constructor(private readonly transport: RpcTransport) {}

	get(key: string): Promise<any> {
		return this.transport.request("Storage/get", { key });
	}

	set(key: string, value: any): Promise<void> {
		return this.transport.request("Storage/set", { key, value });
	}

	remove(key: string): Promise<void> {
		return this.transport.request("Storage/remove", { key });
	}

	clear(): Promise<void> {
		return this.transport.request("Storage/clear", {});
	}

	list(): Promise<any> {
		return this.transport.request("Storage/list", {});
	}
}

class FileSearchService {
	constructor(private readonly transport: RpcTransport) {}

	search(q: string, opts: FileSearchOptions): Promise<FileInfo[]> {
		return this.transport.request("FileSearch/search", { q, opts });
	}
}

class CommandService {
	constructor(private readonly transport: RpcTransport) {}

	updateCommandMetadata(payload: UpdateCommandMetadataPayload): Promise<void> {
		return this.transport.request("Command/updateCommandMetadata", { payload });
	}

	openExtensionPreferences(): Promise<void> {
		return this.transport.request("Command/openExtensionPreferences", {});
	}

	openCommandPreferences(): Promise<void> {
		return this.transport.request("Command/openCommandPreferences", {});
	}
}

class OAuthService {
	constructor(private readonly transport: RpcTransport) {}

	authorize(payload: AuthorizeRequest): Promise<AuthorizeResponse> {
		return this.transport.request("OAuth/authorize", { payload });
	}

	getTokens(id?: string): Promise<TokenSetResponse> {
		return this.transport.request("OAuth/getTokens", { id });
	}

	setTokens(payload: SetTokensRequest): Promise<void> {
		return this.transport.request("OAuth/setTokens", { payload });
	}

	removeTokens(id?: string): Promise<void> {
		return this.transport.request("OAuth/removeTokens", { id });
	}
}

class EventCoreService {
	constructor(private readonly transport: RpcTransport) {}

	handlerActivated(
		handler: (id: string, args: any[]) => void,
	): EventSubscription {
		return this.transport.subscribe("EventCore/handlerActivated", (msg) =>
			handler(msg.id, msg.args),
		);
	}
}

export class Client {
	constructor(private readonly transport: RpcTransport) {
		this.Application = new ApplicationService(this.transport);
		this.UI = new UIService(this.transport);
		this.WindowManagement = new WindowManagementService(this.transport);
		this.Clipboard = new ClipboardService(this.transport);
		this.Storage = new StorageService(this.transport);
		this.FileSearch = new FileSearchService(this.transport);
		this.Command = new CommandService(this.transport);
		this.OAuth = new OAuthService(this.transport);
		this.EventCore = new EventCoreService(this.transport);
	}

	route(msg: string): void {
		this.transport.dispatchMessage(msg);
	}
	Application: ApplicationService;
	UI: UIService;
	WindowManagement: WindowManagementService;
	Clipboard: ClipboardService;
	Storage: StorageService;
	FileSearch: FileSearchService;
	Command: CommandService;
	OAuth: OAuthService;
	EventCore: EventCoreService;
}
