-- Notecase Pro sample script (requires Notecase Pro >= 3.5.0)
--
-- Description:
-- Implements global bookmarks system (i.e. not related to current document only)
-- Bookmarks are stored in a tab-delimited file "global_bookmarks.csv" at the same folder where Notecase keeps config file.
-- You can edit this file manually if you want to reorder the bookmarks in a simple way.
--
-- This script's author, Miroslav Rajcic, hereby waives all copyright 
-- and related or neighboring rights to this script, pursuant to the
-- Creative Commons CC0 Universal relinquishment of rights found at
-- http://creativecommons.org/publicdomain/zero/1.0/

-- make sure app version supports necessary scriptable program commands
nMaj, nMin, nRev = Nc_Config_GetAppVersion()
if (nMaj < 3 or (nMaj == 3 and nMin < 5)) then
	Nc_GUI_MessageBox("ERROR: Script requires NcPro version >= 3.5.0")
	return
end 

strStoreFile = Nc_Config_ConfigDir_Get() .. "global_bookmarks.csv"

-- break string into the array
function lines(str)
  local t = {}
  local i, lstr = 1, #str
  while i <= lstr do
    local x, y = string.find(str, "\r?\n", i)
    if x then t[#t + 1] = string.sub(str, i, x - 1)
    else break
    end
    i = y + 1
  end
  if i <= lstr then t[#t + 1] = string.sub(str, i) end
  return t
end

function prepare_menu(tData)
	-- prepare table version to fill the dialog
	local t = {}
	
	-- first two items are menu items
	t[#t + 1] = "[ Add current note ]"
	t[#t + 1] = "[ Remove current note ]"
	
	-- the rest are actual bookmarks
	local nSize = #tData
	for i=1, nSize do
		-- extract title only
		local x, y = string.find(tData[i], "\t")
		if x then 
			strTitle = string.sub(tData[i], 1, x - 1)
		else 
			strTitle = tData[i]
		end
		t[#t + 1] = strTitle
	end
	return t
end

function read_bookmarks()
  local t = {}
  local f = io.open(strStoreFile, "r")
	if f ~= nil then
		-- read file content
		local strData = f:read("*all")
		f:close() 
		local lines = lines(strData)
		local nSize = #lines
		for i=1, nSize do
			t[#t + 1] = lines[i]
		end
	end
  return t
end

function write_bookmarks(tData)
	local f = io.open(strStoreFile,"w")
	if f ~= nil then
	local nSize = #tData
		for i=1, nSize do
			f:write(tData[i],"\n")
		end
		f:close()
	end
end

function renumber_table(tData)
	-- renumber the map so no key gaps appear in the new map
	local t = {}
	for key, value in ipairs(tData) do 
		t[#t + 1] = value
	end
	return t
end

function add_current_bookmark(tData)
	local nDocID = Nc_Doc_ID_GetCur()
	local strCurNoteID = Nc_Note_ID_GetCur(nDocID)
	if strCurNoteID == "" then
		Nc_GUI_MessageBox("Error: No selected note found!")
		return
	end
	
	local strPath = Nc_Doc_GetPath(nDocID)
	local strEntry = strPath .. "#" .. strCurNoteID
	local strTitle = Nc_GUI_InputDlg("Bookmark Title", Nc_Note_Title_Get(nDocID, strCurNoteID), "", 0, 1)
	
	tData[#tData + 1] = strTitle .. "\t" .. strEntry
end

function remove_current_bookmark(tData)
	local nDocID = Nc_Doc_ID_GetCur()
	local strCurNoteID = Nc_Note_ID_GetCur(nDocID)
	if strCurNoteID == "" then
		Nc_GUI_MessageBox("Error: No selected note found!")
		return
	end
	
	local strPath = Nc_Doc_GetPath(nDocID)
	local strEntry = strPath .. "#" .. strCurNoteID

	-- match by entry and delete
	local nSize = #tData
	for i=1, nSize do
		-- extract entry part only
		local strEntryPart = ""
		local x, y = string.find(tData[i], "\t")
		if x then 
			strEntryPart = string.sub(tData[i], x+1)
		else 
			strEntryPart = tData[i]
		end
		if strEntry == strEntryPart then
			-- Nc_GUI_MessageBox("remove: found at idx ".. i)
			table.remove(tData, i)
			tData = renumber_table(tData)
			return
		end
	end

end

function exec_bookmark(tData, nIdx)
	local strLine = tData[nIdx]
	local strEntryPart = ""
	local x, y = string.find(strLine, "\t")
	if x then 
		strEntryPart = string.sub(strLine, x+1)
	else 
		strEntryPart = strLine
	end
	
	local strPath = ""
	local strNodeID = ""
	x, y = string.find(strEntryPart, "#")
	if x then 
		strPath = string.sub(strEntryPart, 1, x-1)
		strNodeID = string.sub(strEntryPart, x+1)
	else 
		strPath = strEntryPart
	end
	
	if strPath ~= "" then
		-- find if such document is already open
		nDocFound = 0
		nCount = Nc_App_GetDocCount()
		for i=0, nCount-1 do
			local nDocID = Nc_Doc_ID_GetByIdx(i)
			local strCurPath = Nc_Doc_GetPath(nDocID)
			if strPath == strCurPath then
				nDocFound = 1
				Nc_Doc_MakeCur(nDocID)
			end
		end  
		-- else load doc
		if nDocFound < 1 then
			Nc_Doc_Load(strPath)
		end
		
		-- select note
		Nc_Note_ID_SetCur(strNodeID)
	end
end

-- read bookmarks
local tBookmarks = read_bookmarks()
		
-- show selection dialog
local nSelKey = Nc_GUI_SelectionDlgTbl("Global Bookmarks", prepare_menu(tBookmarks), "Your global bookmarks")
if nSelKey < 0 then
	return
end

-- handle selection result
if nSelKey == 1 then
	add_current_bookmark(tBookmarks)
	write_bookmarks(tBookmarks)
else 
 if nSelKey == 2 then
	 remove_current_bookmark(tBookmarks)
	 write_bookmarks(tBookmarks)
 else
	 exec_bookmark(tBookmarks, nSelKey-2)
 end
end