/*
 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 { platform } from "os";
import type { MakeUserMount } from "../../core";
import { makeMounting } from "./descriptors";
import { mountFuser } from "./native-mods";
import { volumeMountDir } from "../../confs";
import { UserMounts } from "./user-mounts";

type MountsIntoOS = web3n.shell.mounts.MountsIntoOS;

const volumeName = 'PrivacySafe';

export function mountIntoOS(): { makeUserMount: MakeUserMount; unmount: () => void; }|undefined {
	const os = platform();
	let volumePath: string;
	if ((os === 'linux') || (os === 'darwin')) {
		volumePath = volumeMountDir;
	} else {
		// XXX windows will have something like P:
		return;
	}
	try {
		const { getOrMakeUserMounts: makeUserMount, implOfFuserCallbacks } = makeMounting(volumePath);
		const unmount = mountFuser(volumePath, volumeName, implOfFuserCallbacks());
		return { makeUserMount, unmount };
	} catch (err) {
		console.error(`Fail to mount`, err);
		return;
	}
}

export function makeMountsCAP(
	appDomain: string, capsReq: web3n.caps.ShellCAPsSetting['mounts'], userMounts: UserMounts|undefined
): {
	cap: NonNullable<web3n.shell.ShellCAPs['mounts']>
}|undefined {
	if (!userMounts) {
		return;
	} else if (capsReq) {
		return {
			cap: makeCAP(appDomain, capsReq, userMounts)
		};
	} else {
		return;
	}
}

function makeCAP(
	appDomain: string, section: NonNullable<web3n.caps.DeviceMountFSCAPSetting>, userMounts: UserMounts
): MountsIntoOS {
	switch (section) {
		case 'any':
			return {
				mountFile: async (p, f) => userMounts.mountFile(p, f),
				mountFolder: async (p, f) => userMounts.mountFS(p, f),
				unmountPath: async p => userMounts.unmountPath(p),
				unmountFile: async f => userMounts.unmountFile(f),
				unmountFolder: async f => userMounts.unmountFolder(f)
			};
		case 'app':
			return mountsInSection(['apps', appDomain], userMounts);
		case 'mail':
			return mountsInSection(['mail'], userMounts);
		case 'chat':
			return mountsInSection(['chat'], userMounts);
	}
}

function mountsInSection(pathPrefix: string[], userMounts: UserMounts): MountsIntoOS {
	return {
		mountFile: async (p, f) => userMounts.mountFile(pathPrefix.concat(p), f),
		mountFolder: async (p, f) => userMounts.mountFS(pathPrefix.concat(p), f),
		unmountPath: async p => userMounts.unmountPath(pathPrefix.concat(p)),
		unmountFile: async f => userMounts.unmountFile(f),
		unmountFolder: async f => userMounts.unmountFolder(f)
	};
}


Object.freeze(exports);