
local tArgs = { ... }
if #tArgs == 0 then
	print( "Usage: edit <path>" )
	return
end

local sPath = shell.resolve( tArgs[1] )
local bReadOnly = fs.isReadOnly( sPath )
if fs.exists( sPath ) and fs.isDir( sPath ) then
	print( "Cannot edit a directory" )
	return
end

local w,h = term.getSize()
local x,y = 1,1
local scrollX, scrollY = 0,0

local bMenu = false
local nMenuItem = 1

local sStatus = ""
local tLines = {}

local function load()
	tLines = {}
	if fs.exists( sPath ) then
		local file = io.open( sPath, "r" )
		local sLine = file:read()
		while sLine do
			table.insert( tLines, sLine )
			sLine = file:read()
		end
		file:close()
	else
		table.insert( tLines, "" )
	end
end

local function save()
	local file = io.open( sPath, "w" )
	if file then
		for n, sLine in ipairs( tLines ) do
			file:write( sLine .. "\n" )
		end
		file:close()
		return true
	end
	return false
end

local function redrawText()
	for y=1,h-1 do
		term.setCursorPos( 1 - scrollX, y )
		term.clearLine()

		local sLine = tLines[ y + scrollY ]
		if sLine ~= nil then
			term.write( sLine )
		end
	end
	term.setCursorPos( x - scrollX, y - scrollY )
end

local function redrawLine()
	local sLine = tLines[y]
	term.setCursorPos( 1 - scrollX, y - scrollY )
	term.clearLine()
	term.write( sLine )
	term.setCursorPos( x - scrollX, y - scrollY )
end

local tMenuItems = { "Save", "Exit" }

local function redrawMenu()
    term.setCursorPos( 1, h )
	term.clearLine()

	if not bMenu then
		term.write( sStatus )
	else
		for n,sItem in ipairs( tMenuItems ) do
			if n == nMenuItem then
				term.write( "["..sItem.."]" )
			else
				term.write( " "..sItem.." " )
			end
		end
	end
	
    term.setCursorPos( x - scrollX, y - scrollY )
end

local function setStatus( _sText )
	sStatus = _sText
	redrawMenu()
end

local function setCursor( x, y )
	local screenX = x - scrollX
	local screenY = y - scrollY
	
	local bRedraw = false
	if screenX < 1 then
		scrollX = x - 1
		screenX = 1
		bRedraw = true
	elseif screenX > w then
		scrollX = x - w
		screenX = w
		bRedraw = true
	end
	
	if screenY < 1 then
		scrollY = y - 1
		screenY = 1
		bRedraw = true
	elseif screenY > h-1 then
		scrollY = y - (h-1)
		screenY = h-1
		bRedraw = true
	end
	
	if bRedraw then
		redrawText()
	end
	term.setCursorPos( screenX, screenY )
end

load()

term.clear()
term.setCursorPos(x,y)
term.setCursorBlink( true )

redrawText()
setStatus( "Press Ctrl to access menu" )

local bRunning = true
local tMenuFunctions = {
	["Exit"] = function()
		bRunning = false
	end,
	["Save"] = function()
		if save() then
			setStatus( "Saved to "..sPath )
		else
			setStatus( "Access denied" )
		end
	end,
}

local function doMenuItem( _n )
	local fnMenu = tMenuFunctions[ tMenuItems[_n] ]
	if fnMenu then
		fnMenu()
	end

	bMenu = false
	term.setCursorBlink( true )
	redrawMenu()
end

while bRunning do
  local sEvent, param = os.pullEvent()
  if sEvent == "key" then
    if param == 200 then
		-- Up
		if not bMenu then
			-- Move cursor up
			if y > 1 then
				y = y - 1
				x = math.min( x, string.len( tLines[y] ) + 1 )
				setCursor( x, y )
			end
		end
		
	elseif param == 208 then
		-- Down
		if not bMenu then
			-- Move cursor down
			if y < #tLines then
				y = y + 1
				x = math.min( x, string.len( tLines[y] ) + 1 )
				setCursor( x, y )
			end
		end
	
	elseif param == 203 then
		-- Left
		if not bMenu then
			-- Move cursor left
			if x > 1 then
				x = x - 1
				setCursor( x, y )
			end
		else
			-- Move menu left
			nMenuItem = nMenuItem - 1
			if nMenuItem < 1 then
				nMenuItem = #tMenuItems
			end
			redrawMenu()
		end
			
		
	elseif param == 205 then
		-- Right
		if not bMenu then
			-- Move cursor right
   		 	if x < string.len( tLines[y] ) + 1 then
				x = x + 1
				setCursor( x, y )
		  	end
		else
			-- Move menu right
			nMenuItem = nMenuItem + 1
		  	if nMenuItem > #tMenuItems then
				nMenuItem = 1
		  	end
		  	redrawMenu()
		end
		
	elseif param == 14 then
		-- Backspace
		if not bMenu then
   		 	if x > 1 then
				-- Remove character
				local sLine = tLines[y]
				tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
				redrawLine()
		
				x = x - 1
				setCursor( x, y )
			
			elseif y > 1 then
				-- Remove newline
				local sPrevLen = string.len( tLines[y-1] )
				tLines[y-1] = tLines[y-1] .. tLines[y]
				table.remove( tLines, y )
				redrawText()
			
				x = sPrevLen + 1
				y = y - 1
				setCursor( x, y )
		  	end
		end
		
	elseif param == 28 then
		-- Enter
		if not bMenu then
			-- Newline
			local sLine = tLines[y]
			tLines[y] = string.sub(sLine,1,x-1)
			table.insert( tLines, y+1, string.sub(sLine,x) )
			redrawText()
		
			x = 1
			y = y + 1
			setCursor( x, y )		
			
		else
			-- Menu selection
			doMenuItem( nMenuItem )
		end
		
	elseif param == 29 then
		-- Menu toggle
		bMenu = not bMenu
		if bMenu then
			term.setCursorBlink( false )
			nMenuItem = 1
		else
			term.setCursorBlink( true )
		end
		redrawMenu()
	
	end
		
  elseif sEvent == "char" then
	if not bMenu then
    	-- Input text
		local sLine = tLines[y]
		tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
		redrawLine()
	
		x = x + string.len( param )
		setCursor( x, y )
	
	else
		-- Select menu items
		for n,sMenuItem in ipairs( tMenuItems ) do
			if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then
				doMenuItem( n )
				break
			end
		end
	end
  end
end

term.clear()
term.setCursorBlink( false )
term.setCursorPos( 1, 1 )
