#!/usr/bin/osascript
(*
Script originally written by Naupaka Zimmerman, modified by iandol
August 10, 2017 -- current version V2020.1.14

MIT License

Copyright (c) 2017 Naupaka Zimmerman

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*)

-- Trim whitespace, from http://macscripter.net/viewtopic.php?id=18519
on trim(someText)
	repeat until someText does not start with " "
		set someText to text 2 thru -1 of someText
	end repeat
	
	repeat until someText does not end with " "
		set someText to text 1 thru -2 of someText
	end repeat
	
	return someText
end trim

-- Function to split returned values on a character into an array
-- and also to parse out only those that match the query string.
-- E.g. if you have a folder of groups called "Manuscripts/", this will
-- find all groups with that word in their path and export them.
-- It will also work with the name of just a single specific group.
-- Based on code from this page: 
-- http://erikslab.com/2007/08/31/applescript-how-to-split-a-string/
on theSplit(allGroups, theDelimiter, myGroups)
	-- set delimiters to delimiter to be used
	set AppleScript's text item delimiters to theDelimiter
	-- create the array
	set groupArray to every text item of allGroups
	set theSelectedList to {}
	repeat with currentGroup in myGroups
		set currentGroup to my trim(currentGroup)
		repeat with thisGroup in groupArray
			if ((thisGroup as string) contains (currentGroup as string)) then
				-- use sed to strip out all folder names from the group name returned from bookends
				-- this leaves only group name 
				set cmd to "echo \"" & thisGroup & "\"| sed \"s/.*\\/\\(.*\\)/\\1/\"" as string
				set sedResult to (do shell script cmd)
				-- if there's a match, append parsed group name onto end of list
				set end of theSelectedList to sedResult
			end if
		end repeat
	end repeat
	return theSelectedList
end theSplit

on run argv
	--start time
	set originalT to (time of (current date))
	--version
	set myVersion to 1.14
	-- store default delimiters
	set oldDelimiters to AppleScript's text item delimiters
	-- protect titles?
	set protectBibTitles to (system attribute "protectBibTitles" as string)
	if protectBibTitles is "true" then
		set protectBibTitles to true
	else
		set protectBibTitles to false
	end if
	-- get JSON option
	set toJSON to (system attribute "BibTeXtoJSON" as string)
	if toJSON is "true" then
		set toJSON to true
	else
		set toJSON to false
	end if
	-- get export name option
	set fmtName to (system attribute "customExportFormat" as string)
	if fmtName is "" then
		set fmtName to "BibTeX"
	end if
	-- check that pandoc-citeproc is available
	set cpPath to "/usr/local/bin/pandoc-citeproc"
	set isCiteproc to false
	tell application "Finder" to if exists cpPath as POSIX file then set isCiteproc to true
	
	-- parse input
	set homePath to POSIX path of (path to home folder)
	if (count of argv) > 1 then
		set myPath to POSIX path of homePath & (item 1 of argv)
		set theGroups to items 2 thru -1 of argv
	else if (count of argv) > 0 then
		set myPath to POSIX path of homePath & (item 1 of argv)
		set theGroups to "Selection"
	else
		set myPath to POSIX path of (path to desktop)
		set theGroups to "Selection"
	end if
	set AppleScript's text item delimiters to " "
	set myGroupsToExport to theGroups as text
	
	-- parse based on comma delimiter
	set AppleScript's text item delimiters to ","
	set myGroupsToExport to every text item of myGroupsToExport
	set AppleScript's text item delimiters to oldDelimiters
	
	tell application "Bookends"
		-- get a list of all groups in open library
		set allGroups to «event ToySRGPN» given «class PATH»:"true"
		-- prepend the default bookends groups
		set allGroups to "All" & return & "Hits" & return & "Attachments" & return & "Selection" & return & allGroups
		-- split up those groups into elements of an array
		-- 'return' here, as the middle parameter, is the return or newline character
		set myGroupArray to my theSplit(allGroups, return, myGroupsToExport)
	end tell
	
	if myGroupArray is {} then
		set output to "No groups matched your input..."
	else
		display notification "Running " & fmtName & " conversion, please wait..." with title "Bookends to BibTeX exporter V" & myVersion
		-- set output string based on parsed input parameters or defaults
		set AppleScript's text item delimiters to ", "
		set output to ("Path: " & myPath & " | " & "Groups:" & myGroupArray & "." as string)
		set AppleScript's text item delimiters to oldDelimiters -- change back to default
	end if
	
	-- loop over each folder matching the pattern and export each to a bibtex file
	repeat with myGroup in myGroupArray
		set thisFile to (myPath & "/" & (myGroup as string) & ".bib") as POSIX file
		set thisJSONFile to (myPath & "/" & (myGroup as string) & ".json") as POSIX file
		set quotedName to quoted form of POSIX path of thisFile
		set quotedJSONName to quoted form of POSIX path of thisJSONFile
		set myFile to open for access thisFile with write permission
		set eof of myFile to 0 --make sure we overwrite
		
		try
			tell application "Bookends"
				-- get a list of all unique reference IDs in the specified group 
				set myListString to «event ToySRUID» myGroup as string
			end tell
			-- convert to list 
			set AppleScript's text item delimiters to return
			set myList to text items of myListString
			-- set up the loop to batch fetch sets of references, 
			-- in theory this should be more efficient, 
			-- and saves around 1-2 seconds per 1000 exported
			set steps to 25
			set listLength to length of myList
			set nLoop to round (listLength / steps) rounding up
			set thisLoop to 1
			
			set progress total steps to nLoop
			set progress completed steps to 0
			set progress description to "Processing group: " & myGroup & " # refs: " & listLength
			set progress additional description to "...please be patient"
			
			-- iterate through list writing each entry
			repeat while thisLoop is less than or equal to nLoop
				-- set the batch index range
				set startindex to (steps * thisLoop) - (steps - 1)
				set endindex to (steps * thisLoop)
				if endindex is greater than listLength then
					set endindex to listLength
				end if
				-- select current batch of items
				set thisListItems to items startindex thru endindex of myList
				set thisList to thisListItems as string
				
				-- fetch the BibTeX
				tell application "Bookends"
					set myBibTex to «event ToySGUID» thisList given «class RRTF»:"false", string:fmtName
				end tell
				
				-- write out as UTF-8, from: http://macscripter.net/viewtopic.php?id=24534
				write myBibTex to myFile as «class utf8»
				
				-- update progress bar        
				set progress completed steps to thisLoop
				set progress additional description to "Reference block: " & thisLoop & " completed..."
				
				-- update the loop number
				set thisLoop to thisLoop + 1
				
			end repeat -- thisLoop
			-- Reset the progress information
			set progress total steps to 0
			set progress completed steps to 0
			set progress description to ""
			set progress additional description to ""
		on error
			try
				close access myFile
				set AppleScript's text item delimiters to oldDelimiters
			end try
			return "Problem processing references..."
		end try
		
		close access myFile
		
		if protectBibTitles is true then
			-- To force case of the title we have to wrap it in an extra { }
			-- so we have to do it with sed (grrr applescript!)
			set permBibPath to POSIX path of thisFile
			set tempBibPath to permBibPath & ".tmp"
			set permBibPath to quoted form of permBibPath
			set tempBibPath to quoted form of tempBibPath
			set cmd to "sed -E 's/(title = )({[^}]*})/\\1{\\2}/g' " & permBibPath & " > " & tempBibPath & " && mv " & tempBibPath & " " & permBibPath
			do shell script cmd
			set output to output & "(protect case)"
		end if
		-- Convert to JSON? JSON is much faster to parse for pandoc-citeproc
		if (toJSON is true) and (isCiteproc is true) then
			set cmd to cpPath & " -j " & quotedName & " > " & quotedJSONName
			try
				do shell script cmd
				do shell script "rm -f " & quotedName
				set output to output & "(to JSON)"
			on error errorMessage number errorNumber
				do shell script "rm -f " & quotedJSONName
				display notification "Error: " & errorMessage with title "JSON Error: " & errorNumber subtitle "Check your cite keys."
			end try
		end if
		
	end repeat
	
	set newT to (time of (current date))
	set diffT to newT - originalT
	set output to output & " | took " & diffT & " seconds"
	
	set AppleScript's text item delimiters to oldDelimiters
	display notification output with title "Bookends to BibTeX exporter V" & myVersion
	
end run