import { writable } from "svelte/store"
import { fs_check_response, fs_path_url, type FSNode } from "./FilesystemAPI.svelte"
import { loading_finish, loading_start } from "lib/Loading"
import { get_user } from "lib/NovaAPI"

const bookmarks_file = "/me/.nova/bookmarks.json"

export type Bookmark = {
	id: string,
	path: string,
	icon: string,
	label: string,
}

export let bookmarks_store = writable<Bookmark[]>(
	[],
	(set: (value: Bookmark[]) => void) => {
		bookmarks_get().then((bm: Bookmark[]) => {
			set(bm)
		}).catch((err: any) => {
			alert("Could not fetch bookmarks:\n" + JSON.stringify(err))
		})
	},
)

export const bookmarks_get = async (): Promise<Bookmark[]> => {
	try {
		loading_start()
		const user = await get_user()
		if (user === null) {
			return []
		}

		const bookmarks = await fs_check_response(
			await fetch(fs_path_url(bookmarks_file), { cache: "no-store" })
		) as Bookmark[]

		// Sanity checks
		for (const bookmark of bookmarks) {
			if (typeof bookmark.id !== "string") { bookmark.id = "" }
			if (typeof bookmark.path !== "string") { bookmark.path = "" }
			if (typeof bookmark.icon !== "string") { bookmark.icon = "" }
			if (typeof bookmark.label !== "string") { bookmark.label = "" }
		}

		console.debug("Fetched", bookmarks.length, "bookmarks:", bookmarks)
		bookmarks_store.set(bookmarks)
		return bookmarks
	} catch (err) {
		// If the bookmarks were not found when we return an empty bookmarks
		// list
		if (
			err.value !== "path_not_found" &&
			err.value !== "forbidden" &&
			err.value !== "authentication_required"
		) {
			throw err
		} else {
			return []
		}
	} finally {
		loading_finish()
	}
}

export const bookmarks_save = async (bookmarks: Bookmark[]) => {
	try {
		loading_start()

		await fs_check_response(
			await fetch(
				fs_path_url(bookmarks_file) + "?make_parents=true",
				{ method: "PUT", body: JSON.stringify(bookmarks) },
			)
		)
		console.debug("Saved", bookmarks.length, "bookmarks:", bookmarks)
		bookmarks_store.set(bookmarks)
	} finally {
		loading_finish()
	}
}

export const bookmark_add = async (node: FSNode): Promise<Bookmark[]> => {
	try {
		loading_start()

		// Get bookmarks
		const bookmarks = await bookmarks_get()

		// Add new bookmark
		bookmarks.push({
			id: node.id,
			path: node.path,
			icon: "bookmark",
			label: node.name,
		})

		// Save new bookmarks
		await bookmarks_save(bookmarks)
		return bookmarks
	} finally {
		loading_finish()
	}
}

export const bookmark_del = async (id: string): Promise<Bookmark[]> => {
	let bookmarks: Bookmark[] = []
	try {
		loading_start()

		// Get bookmarks
		bookmarks = await bookmarks_get()

		// Delete bookmark
		for (let i = 0; i < bookmarks.length; i++) {
			if (bookmarks[i].id === id) {
				console.debug("Deleting bookmark at index", i, bookmarks[i])
				bookmarks.splice(i, 1)
				break
			}
		}

		// Save new bookmarks
		await bookmarks_save(bookmarks)
	} finally {
		loading_finish()
	}
	return bookmarks
}

export const is_bookmark = (bookmarks: Bookmark[], id: string): boolean => {
	for (const bm of bookmarks) {
		if (bm.id === id) {
			return true
		}
	}
	return false
}
