-- begin script

property pCR : ASCII character 13
property pLF : ASCII character 10

property pClassicMacLineEnding : pCR
property pUnixLineEnding : pLF
property pDOSLineEnding : (pCR & pLF as text)

property pLogFileName : "Convert Line Endings.log"

property pLogFolder : ""
property pTotalNum : 0
property pNumProcessed : 0
property pDesiredLineEnding : ""

--------------------------------------------------------------------------------------------

-- run entry
on run
	-- about
	my DisplayAboutBox("Quit")
end run

--------------------------------------------------------------------------------------------

-- droplet entry
on open itemList
	
	-- about
	
	my DisplayAboutBox("Continue")
	
	-- ask user to specify desired line endings
	
	set dResult to display dialog ¬
		"Please specify the line endings to which you want to convert these " & ¬
		"files." buttons {"Classic Mac OS (CR)", "Mac OS X / Unix (LF)", ¬
		"DOS (CR+LF)"} default button 2 with icon note
	
	if dResult's button returned is "Classic Mac OS (CR)" then
		
		set pDesiredLineEnding to pClassicMacLineEnding
		my LogEntry("User specified \"Classic Mac OS (CR)\" line endings")
		
	else if dResult's button returned is "Mac OS X / Unix (LF)" then
		
		set pDesiredLineEnding to pUnixLineEnding
		my LogEntry("User specified \"Mac OS X / Unix (LF)\" line endings")
		
	else if dResult's button returned is "DOS (CR+LF)" then
		
		set pDesiredLineEnding to pDOSLineEnding
		my LogEntry("User specified \"DOS (CR+LF)\" line endings")
		
	end if
	
	-- set up
	
	set pTotalNum to 0
	set pNumProcessed to 0
	set pLogFolder to the path to the desktop from user domain
	
	my LogEntry("Starting up")
	
	-- start processing dropped items
	
	repeat with nextItem in itemList
		
		set filename to my FilenameFromPath(nextItem)
		
		if the last character of (nextItem as text) is ":" then
			
			-- this item is a folder
			
			set dResult to display dialog ("\"" & filename & "\" is a folder. " & ¬
				"Process all files in this folder?") buttons {"Do Not Process", ¬
				"Process All Files"} with icon stop default button 2
			
			if dResult's button returned is "Process All Files" then
				
				-- process all files in this folder
				my ProcessFolder(nextItem)
				
			end if
		else
			
			-- this item is a file
			my ProcessFile(nextItem)
		end if
		
		-- report results
		set logFile to (pLogFolder as text) & pLogFileName
		set dResult to display dialog ¬
			"Converted line endings in " & ¬
			pNumProcessed & " of " & pTotalNum & " items. A log file of the entire " & ¬
			"operation is located here:" & return & return & ¬
			logFile's POSIX path buttons {"View Log Now", "Quit"} default button 2 ¬
			with icon note
		
		-- view log
		if dResult's button returned is "View Log Now" then
			do shell script ("open " & the quoted form of logFile's POSIX path)
		end if
		
	end repeat
	
	my LogEntry("Finished")
	
end open

--------------------------------------------------------------------------------------------

on ProcessFolder(thisFolder)
	
	script FolderLister
		global fileList
		
		on GetFileList(pathToFolder)
			set theListRef to a reference to list folder pathToFolder without invisibles
			repeat with nextItem in theListRef
				set itemPath to (pathToFolder & nextItem as text)
				if folder of (info for alias itemPath) then
					GetFileList(itemPath & ":" as text)
				else
					set the fileList to fileList & itemPath
				end if
			end repeat
		end GetFileList
		
		on Listfolder(pathToFolder)
			set fileList to {}
			GetFileList(pathToFolder)
			return fileList
		end Listfolder
	end script
	
	-- get the file list
	tell FolderLister to set fileList to Listfolder(thisFolder)
	
	-- process each item in the list
	repeat with nextItem in fileList
		if the last character of (nextItem as text) is not ":" then
			-- item is not a folder - process it
			my ProcessFile(nextItem)
		end if
	end repeat
	
end ProcessFolder

--------------------------------------------------------------------------------------------

on ProcessFile(thisFile)
	
	set process to true
	
	-- get the file name
	
	set filename to my FilenameFromPath(thisFile)
	
	-- determine the Unix file type
	
	set fileType to my GetUnixFileType(thisFile)
	
	if fileType does not contain "text" then
		-- ask user if we should process this file
		set process to button returned of (display dialog "The file \"" & filename & "\" appears to be a file of type \"" & fileType & "\". Are you sure you want to convert line endings in this file?" buttons {"Do Not Convert", "Convert"} default button 1 with icon stop) is "Convert"
	end if
	
	-- increment item counter
	
	set pTotalNum to pTotalNum + 1
	
	if process then
		
		-- process the file
		
		my LogEntry("Processing \"" & filename & "\" with file type: " & fileType)
		
		set pNumProcessed to pNumProcessed + 1
		
		set posixPath to the quoted form of thisFile's POSIX path
		
		if pDesiredLineEnding is pClassicMacLineEnding then
			
			-- convert to classic Mac OS (CR)
			do shell script "perl -pi -e 's/(\\r\\n|\\n|\\r)/\\r/g' " & posixPath
			
		else if pDesiredLineEnding is pUnixLineEnding then
			
			-- convert to Mac OS X / Unix (LF)
			do shell script "perl -pi -e 's/(\\r\\n|\\n|\\r)/\\n/g' " & posixPath
			
		else if pDesiredLineEnding is pDOSLineEnding then
			
			-- convert to DOS (CR+LF)
			do shell script "perl -pi -e 's/(\\r\\n|\\n|\\r)/\\r\\n/g' " & posixPath
			
		end if
		
	else
		my LogEntry("Skipping \"" & filename & "\" with file type \"" & fileType & "\" at user's request")
	end if
	
end ProcessFile

--------------------------------------------------------------------------------------------

on DisplayAboutBox(buttonName)
	display dialog "This AppleScript application converts line " & ¬
		"endings of text files between Mac OS (CR), Unix (LF), or DOS (CR+LF) " & ¬
		"line endings. " & return & return & "To use the application, drag and drop " & ¬
		"one or more text files (or folders containing text files) onto the application " & ¬
		"icon." & return & return & "Note: The script does not duplicate files, but " & ¬
		"rather replaces all line endings in the files. If you think you may need " & ¬
		"unedited copies of your files, you should backup copies of your files before " & ¬
		"proceeding." buttons {buttonName} default button 1 giving up after 15 ¬
		with icon note
end DisplayAboutBox

--------------------------------------------------------------------------------------------

on FilenameFromPath(thePath)
	set oldDelimiters to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ":"
	set pathAsList to text items of (thePath as text)
	if the last character of (thePath as text) is ":" then
		set idx to -2 -- (the number of text items in thePath) - 1
	else
		set idx to -1
	end if
	set filename to item idx of pathAsList
	set AppleScript's text item delimiters to oldDelimiters
	return filename
end FilenameFromPath

--------------------------------------------------------------------------------------------

on GetUnixFileType(thisFile)
	set shellResult to do shell script "file " & the quoted form of POSIX path of thisFile
	
	set saveDelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ":"
	set resultList to the text items of shellResult
	set AppleScript's text item delimiters to saveDelims
	
	set fileType to resultList's item 2
	set fileType to characters 2 through (the count of characters in fileType) of fileType
	
	return (fileType as text)
end GetUnixFileType

--------------------------------------------------------------------------------------------

on FormatDateTime(theDate)
	set theDate to theDate as date
	set dd to text -2 thru -1 of ("0" & theDate's day)
	copy theDate to tempDate
	set the month of tempDate to January
	set mm to text -2 thru -1 of ¬
		("0" & 1 + (theDate - tempDate + 1314864) div 2629728)
	set yy to text -1 thru -4 of ((year of theDate) as text)
	set hh to time string of theDate
	return (yy & mm & dd & " @ " & hh as text)
end FormatDateTime

--------------------------------------------------------------------------------------------

on LogEntry(someText)
	try
		set logFile to (pLogFolder as text) & pLogFileName
		set logRef to open for access (file logFile) with write permission
		if logRef ≠ 0 then
			write FormatDateTime(current date) & ": " & someText & return starting at eof to logRef
			close access logRef
		end if
	end try
end LogEntry

-- end script