OneOS.LoadAPI('/System/API/Bedrock.lua')
-- Bedrock.ProgramPath = shell.getRunningProgram()

local program = Bedrock:Initialise()

local settings = nil
local dontSave = false
local lastCheck = {}

local function saveSettings()
	if not dontSave then
		local h = OneOS.FS.open('/Desktop/.Desktop.settings', 'w')
		if h then
			h.write(textutils.serialize(settings))
			h.close()
		end
	end
end

local function loadSettings()
	local h = OneOS.FS.open('/Desktop/.Desktop.settings', 'r')
	if h then
		textutils.unserialize(h.readAll())
		h.close()
	end
end

local function tidyIcons(all)
	dontSave = true
	local minX = 1 + math.ceil((Drawing.Screen.Width - FileIcon.Width * math.floor(Drawing.Screen.Width / FileIcon.Width)) / 2)
	local x = minX
	local y = 2

	for i, icon in ipairs(program:GetObjects('FileIcon')) do
		if all or (icon.X == 0 and icon.Y == 0) then
			icon.X = x
			icon.Y = y
		end
		x = x + icon.Width

		if x + icon.Width - 1 > Drawing.Screen.Width then
			x = minX
			if y + 2 * icon.Height + 1 <= Drawing.Screen.Height then
				y = y + icon.Height + 1
			end			
		end
	end
	dontSave = false
	saveSettings()
end

local function updateIcons()
	for i, v in ipairs(OneOS.FS.list('/Desktop/')) do
		if v:sub(1,1) ~= '.' then
			local x = 0
			local y = 0
			if settings and settings[v] then
				x = settings[v].X
				y = settings[v].Y
			end
			program:AddObject({
				X = x,
				Y = y,
				Type = 'FileIcon',
				Path = '/Desktop/' .. v,
				OnUpdate = function(self, value)
					if value == 'X' or value == 'Y' then
						settings = settings or {}
						settings[v] = settings[v] or {}
						settings[v].X = self.X
						settings[v].Y = self.Y
						saveSettings()
					elseif value == 'Selected' then
						local label = self:GetObject('NameLabel')
						if label then
							label.BackgroundColour = (self.Selected and colours.blue or colours.transparent)
							label.TextColour = (self.Selected and colours.white or colours.black)
						end

						if self.Selected then
							for i, v in ipairs(program:GetObjects('FileIcon')) do
								if v ~= self then
									v.Selected = false
								end
							end
						end
					end
				end
			})
		end
	end
	tidyIcons()
end

local searchTimeout

local function showSearch()
	searchTimeout = nil
	if program.View.ChildOffset.Y ~= 3 then
		program.View:AnimateValue('Y', nil, 3, 0.4, function()
		end, program.View.ChildOffset)
	end
	local searchTextBox = program:GetObject('SearchTextBox')
	local searchView = program:GetObject('SearchView')

	program:SetActiveObject(searchTextBox)
	searchTextBox.OnChange = function()
		searchView:OnSearch(searchTextBox.Text)
	end
	searchView:OnSearch(searchTextBox.Text)
end

local function closeSearch()
	program:SetActiveObject(program.View)
	OneOS.Log.i('Close')
	if program.View.ChildOffset.Y ~= 0 then
		program.View:AnimateValue('Y', nil, 0, 0.4, function()
		end, program.View.ChildOffset)
	end
	program:GetObject('SearchView').Visible = false
	searchTimeout = program:StartTimer(function(_, timer)
		if timer == searchTimeout then
			program:GetObject('SearchTextBox').Text = ''
		end
	end, 30)
end

local dragStart
local dragTimer

function ViewClick(self, event, side, x, y)
	if program.DragIcon and event == 'mouse_drag' then
		program.DragIcon.X = x - program.DragIcon.DragX
		program.DragIcon.Y = y - program.DragIcon.DragY
		program.DragIcon:OnIconDrag(x, y)
		program.IconDragTimer = program:StartTimer(function(_,timer)
			if timer and timer == program.IconDragTimer then
				program.IconDragTimer = nil
				program.DragIcon = nil
			end
		end, 0.8)
	elseif self.Visible and not self.IgnoreClick then
		if program.View.ChildOffset.Y ~= 3 or y <= 3 then
			for i = #self.Children, 1, -1 do --children are ordered from smallest Z to highest, so this is done in reverse
				local child = self.Children[i]
				if self:DoClick(child, event, side, x, y) then
					if self.OnChildClick then
						self:OnChildClick(child, event, side, x, y)
					end
					return true
				end
			end
		end

		if event == 'mouse_click' and self.OnClick and self:OnClick(event, side, x, y) ~= false then
			return true
		elseif event == 'mouse_drag' and self.OnDrag and self:OnDrag(event, side, x, y) ~= false then
			return true
		elseif event == 'mouse_scroll' and self.OnScroll and self:OnScroll(event, side, x, y) ~= false then
			return true
		else
			return false
		end
	else
		return false
	end
end

OneOS.Indexer.OnIndex = function()		
	OneOS.Log.i('Files changed')
	updateIcons()
end

program:Run(function()
	program.View.BackgroundColour = OneOS.System.Settings.DesktopColour
	OneOS.System.Settings:OnUpdate(function(key)
		if key == 'DesktopColour' then
			program.View.BackgroundColour = OneOS.System.Settings.DesktopColour
		end
	end)

	loadSettings()
	updateIcons()
	program.View.ChildOffset = {X = 0, Y = 0}

	program.View.Click = ViewClick

	program.View.OnClick = function(self, event, side, x, y)
		if program.View.ChildOffset.Y == 3 then
			if y >= 4 then
				closeSearch()
			else
				return false
			end
		else
			dragStart = y
			dragTimer = program:StartTimer(function(_, timer)
				if timer == dragTimer then
					dragStart = nil
					if program.View.ChildOffset.Y >= 3 then
						showSearch()
					else
						closeSearch()
					end
				end
			end, 1)
		end
	end
	-- TODO: search
	-- program.View.OnDrag = function(self, event, side, x, y)
	-- 	if dragStart then
	-- 		program.View.ChildOffset.Y = y - dragStart
	-- 		program.View:ForceDraw()

	-- 		OneOS.Log.i('drag')
	-- 		dragTimer = program:StartTimer(function(_, timer)
	-- 		OneOS.Log.i('times up')
	-- 		OneOS.Log.i(timer)
	-- 			if timer == dragTimer then
	-- 		OneOS.Log.i('right timer')
	-- 				xdragStart = nil
	-- 		OneOS.Log.i('trhee')
	-- 				if program.View.ChildOffset.Y >= 3 then
	-- 					showSearch()
	-- 				else
	-- 					closeSearch()
	-- 				end
	-- 			end
	-- 		end, 1)
	-- 	end
	-- end

	program.View.OnKeyChar = function(self, event, keychar)
		if keychar == keys.space and not program:GetObject('SearchView').Visible then
			showSearch()
			return false
		end
	end

	program:SetActiveObject(program.View)

	program:GetObject('CancelLabel').OnClick = function()
		closeSearch()
	end

	program:GetObject('SearchButton').OnClick = function()
		showSearch()
	end

	program:GetObject('ShutdownButton').OnClick = function()
		OneOS.Shutdown()
	end

	program:GetObject('RestartButton').OnClick = function()
		OneOS.Restart()
	end

	-- local function check()
	-- 	local newCheck = OneOS.FS.list('/Desktop/')
	-- 	if #newCheck ~= #lastCheck then
	-- 		return true
	-- 	end

	-- 	for i, v in ipairs(newCheck) do
	-- 		if lastCheck[i] ~= v then
	-- 			local ok = false
	-- 			for i2, v2 in ipairs(lastCheck) do
	-- 				if v == v2 then
	-- 					ok = true
	-- 					break
	-- 				end
	-- 			end
	-- 			if not ok then
	-- 				return true
	-- 			end
	-- 		end
	-- 	end
	-- 	return false
	-- end

	-- lastCheck = OneOS.FS.list('/Desktop/')

	-- program:StartRepeatingTimer(function()
	-- 	if check() then
	-- 		refresh()
	-- 	end
	-- end, 5)

end)