--!nonstrict
-- © 2008 David Given.
-- WordGrinder is licensed under the MIT open source license. See the COPYING
-- file in this distribution for the full text.

local NextCharInWord = wg.nextcharinword
local ReadU8 = wg.readu8
local string_len = string.len
local string_char = string.char
local string_format = string.format
local string_gsub = string.gsub

local style_tab: {[string]: string} =
{
	["H1"] = '.NH 1',
	["H2"] = '.NH 2',
	["H3"] = '.NH 3',
	["H4"] = '.NH 4',
	["P"] =  '.LP',
	["L"] =  '.IP "" 3',
	["LB"] = '.IP \\[bu] 3',
	["LN"] = 'special',
	["Q"] =  '.IP',
	["V"] =  '.IP',
	["RAW"] = '',
	["PRE"] = '.LD 1',
}

local function callback(writer, document)
	local currentstyle = nil
	local ul = false
	local it = false
	local bf = false
	local embedded = false
	local linestart = true
	
	local function newline()
		if not linestart then
			writer("\n")
		end
		linestart = true
	end

	local function emit_text(s)
		if linestart then
			s = string_gsub(s, "^([.'])", '\\%1')
			s = string_gsub(s, '^%s+', '')
			linestart = false
		end
		
		if embedded then
			s = string_gsub(s, '"', '\\"')
		end

		s = string_gsub(s, '\\', '\\\\')
		
		local o: number? = 1
		local n = string_len(s)
		
		while o and (o <= n) do
			local c = ReadU8(s, o)
			o = NextCharInWord(s, o)
			if (c < 127) then
				writer(string_char(c))
			else
				writer(string_format('\\[u%04X]', c))
			end
		end
	end
	
	local function changestate(newit, newul, newbf)
		if newul and not ul then
			newline()
			writer('.UL "')
			embedded = true
			linestart = false
		end

		if newit and not newbf then
			writer('\\fI')
			linestart = false
		elseif newit and newbf then
			writer('\\f(BI')
			linestart = false
		elseif not newit and newbf then
			writer('\\fB')
			linestart = false
		elseif not newit and not newbf and (it or bf) then
			writer('\\fR')
			linestart = false
		end
		
		if not newul and ul then
			writer('"\n')
			embedded = false
			linestart = true
		end
		
		it = newit
		ul = newul
		bf = newbf
	end
	
	return ExportFileUsingCallbacks(document,
	{
		prologue = function()
			writer('.\\" This document automatically generated by '..
				'WordGrinder '..VERSION..'.\n')
			writer('.\\" Use the .ms macro package!\n')
			writer('.TL\n')
			emit_text(currentDocument.name)
			writer('\n')
			linestart = true
		end,
		
		text = emit_text,
		
		rawtext = function(s)
			writer(s)
		end,
		
		notext = function()
		end,
		
		italic_on = function()
			changestate(true, ul, bf)
		end,
		
		italic_off = function()
			changestate(false, ul, bf)
		end,
		
		underline_on = function()
			changestate(it, true, bf)
		end,
		
		underline_off = function()
			changestate(it, false, bf)
		end,
		
		bold_on = function()
			changestate(it, ul, true)
		end,
		
		bold_off = function()
			changestate(it, ul, false)
		end,
		
		list_start = function()
		end,
		
		list_end = function()
		end,
		
		paragraph_start = function(para)
			local style = para.style
			if (currentstyle ~= "PRE") or (style ~= "PRE") then
				if (currentstyle == "PRE") then
					writer(".DE\n")
				end
				if (style == "LN") then
					writer(string.format(".IP %d. 3", para.number))
				else
					writer(style_tab[style] or ".LP")
				end
				writer('\n')
			end
			linestart = true
			currentstyle = style
		end,		
		
		paragraph_end = function(style)
			newline()
		end,
		
		epilogue = function()
		end
	})
end

function Cmd.ExportTroffFile(filename)
	return ExportFileWithUI(filename, "Export Troff File", ".tr",
		callback)
end

function Cmd.ExportToTroffString()
	return ExportToString(currentDocument, callback)
end


