/*
 Copyright (C) 2026 3NSoft Inc.

 This program is free software: you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free Software
 Foundation, either version 3 of the License, or (at your option) any later
 version.

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 See the GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along with
 this program. If not, see <http://www.gnu.org/licenses/>.
*/

import type { Notifications } from "../caps/shell/user-notifications";
import type { AppSetter } from "./apps";

type Observer<T> = web3n.Observer<T>;
type ReadonlyFS = web3n.files.ReadonlyFS;
type ReadonlyFile = web3n.files.ReadonlyFile;
type WritableFS = web3n.files.WritableFS;
type FS = web3n.files.FS;
type File = web3n.files.File;
type StorageType = web3n.storage.StorageType;
type AppUnpackProgress = web3n.system.apps.AppUnpackProgress;
type AppEvent = web3n.system.apps.AppEvent;
type SystemParamsForInstalledApp = web3n.system.apps.SystemParamsForInstalledApp;
type AppManifest = web3n.caps.AppManifest;
type CmdParams = web3n.shell.commands.CmdParams;
type DownloadProgress = web3n.system.apps.DownloadProgress;
type AppVersionPacks = web3n.system.apps.AppDistributionList;
type DistChannels = web3n.system.apps.DistChannels;
type Dialogs = web3n.shell.files.Dialogs;
type Clipboard = NonNullable<web3n.shell.ShellCAPs['clipboard']>;

export interface InstalledAppParams {
	appRoot: ReadonlyFS;
	manifest: AppManifest;
	sysParamsForApp: SystemParamsForInstalledApp;
}

export interface SystemPlaces {

	getAppsCodeFS(): Promise<WritableFS>;

	getPackagesFS(): Promise<WritableFS>;

	getPlatformComponentFS(type: StorageType, platformComponentName: string);

	listCurrentApps(): Promise<{ id: string; version: string; }[]>;

	listBundledApps(): Promise<{ id: string; version: string; }[]>;

	listAllAppsPacks(): Promise<{ id: string; versions: string[]; }[]>;

	listAppPacks(id: string): Promise<string[]|undefined>;

	getAppManifest(id: string, version?: string): Promise<AppManifest|undefined>;

	getAppFileBytes(id: string, path: string, appVersion?: string): Promise<Uint8Array|undefined>;

	watchApps(observer: Observer<AppEvent>): () => void;

	addPackBundledApps(appDomain: string, observer: Observer<AppUnpackProgress>): () => void;

	addAppPackFromFolder(appPackFS: ReadonlyFS, observer: Observer<AppUnpackProgress>): () => void;

	addAppPackFromZipFile(appPackFile: ReadonlyFile, observer: Observer<AppUnpackProgress>): () => void;

	installApp(id: string, version: string): Promise<void>;

	uninstallApp(id: string): Promise<void>;

	findInstalledApp(appDomain: string): Promise<InstalledAppParams>;

	appsToLaunchOnSystemStartup(): Promise<string[]>;

	makeDownloadFolder(appDomain: string, version: string): Promise<{
		dir: WritableFS; rmDirOnErr: () => Promise<void>; mvDirOnCompletion: () => Promise<void>;
	}>;

	removeAppPack(id: string, version: string): Promise<void>;

	removeAppData(id: string): Promise<void>;

}

export interface AppDownloader {

	getAppChannels(id: string): Promise<DistChannels>;

	getLatestAppVersion(id: string, channel: string): Promise<string>;

	getAppVersionFilesList(id: string, version: string): Promise<AppVersionPacks>;

	downloadWebApp: (id: string, version: string, observer: Observer<DownloadProgress>) => (() => void);

}

export interface Mounter {

	close(): Promise<void>;

	getPathInOS(f: FS|File): string|undefined;

	mountFS(path: string[], fs: FS): void;

	mountFile(path: string[], file: File): void;

	unmountPath(path: string[]): void;

	unmountFile(file: File): void;

	unmountFolder(fs: FS): void;

}

export interface ShellCAPs {

	makeAllFileDialogOpeners: () => {
		openers: Dialogs; setApp: AppSetter; close(): void;
	},

	makeClipboardCAP: (capsReq: web3n.caps.ShellCAPsSetting['clipboard']) => { cap: Clipboard; }|undefined;

	makeOpenFileCAP: (
		capsReq: web3n.caps.ShellCAPsSetting['openFile'],
		getPathInOS: Mounter['getPathInOS']|undefined
	) => {
		cap: NonNullable<web3n.shell.ShellCAPs['openFile']>;
	}|undefined;

	makeOpenFolderCAP: (
		capsReq: web3n.caps.ShellCAPsSetting['openFolder'],
		getPathInOS: Mounter['getPathInOS']|undefined
	) => {
		cap: NonNullable<web3n.shell.ShellCAPs['openFolder']>;
	}|undefined;

	makeOpenURLCAP: (capsReq: web3n.caps.ShellCAPsSetting['openURL']) => {
		cap: NonNullable<web3n.shell.ShellCAPs['openURL']>;
	}|undefined;

	openInMountedFolderCAP: (
		capsReq: web3n.caps.ShellCAPsSetting['openInMountedFolder'],
		getPathInOS: Mounter['getPathInOS']|undefined
	) => {
		cap: NonNullable<web3n.shell.ShellCAPs['openInMounted']>;
	}|undefined;

	makeMountsCAP: (
		appDomain: string, capsReq: web3n.caps.ShellCAPsSetting['mounts'],
		userMounts: Mounter|undefined
	) => {
		cap: NonNullable<web3n.shell.ShellCAPs['mounts']>
	}|undefined;

	makeNotifications: (triggerCmd: (appDomain: string, cmd: CmdParams) => Promise<void>) => Notifications;

}

