OneOS.LoadAPI('/System/API/Drawing.lua', true)
OneOS.LoadAPI('/System/API/Button.lua', true)
OneOS.LoadAPI('/System/API/Helpers.lua', true)
OneOS.LoadAPI('/System/API/TextInput.lua', true)
OneOS.LoadAPI('/System/API/TextBox.lua', true)
OneOS.LoadAPI('/System/API/Menu.lua', true)
--[[

os.loadAPI('/System/API/Peripheral')
os.loadAPI('/System/API/TextDialogueWindow')
os.loadAPI('/System/API/ButtonDialogueWindow')
]]--

Current = {
	Clicks = {},
	Input = nil,
	CursorPos = {},
	CursorColour = colours.black,
	Menu = nil,
}

Events = {
	
}

InterfaceElements = {
	
}


function Initialise()
	EventRegister('mouse_click', TryClick)
	EventRegister('mouse_drag', TryClick)
	EventRegister('monitor_touch', TryClick)
	EventRegister('mouse_scroll', Scroll)
	EventRegister('key', HandleKey)
	EventRegister('char', HandleKey)
	EventRegister('timer', Update)

	OneOS.ToolBarColour = colours.grey
	OneOS.ToolBarTextColour = colours.white

	settings = OneOS.Settings.Defaults

	local startX = 2
	local startY = 5
	local controlX = startX + 16
	local values = OneOS.Settings:GetValues()
	for k, v in pairs(settings) do
		local value = values[k]
		if v.Type == 'Bool' then
			settings[k].Control = Button:Initialise(controlX, startY, 5, 1, colours.red, colours.white, colours.green, colours.white, nil, function(self, x, y, toggle)
				if not self.Toggle then
					self.Text = 'Yes'
					self.Width = 5
				else
					self.Text = 'No'
					self.Width = 4
				end
				OneOS.Settings:SetValue(k, not self.Toggle)
				return true
			end, 'Yes', value)
			if not value then
				settings[k].Control.Text = 'No'
				settings[k].Control.Width = 4
			end
		elseif v.Type == 'Colour' then
			local x = controlX + 1
			_colours = {
				colours.white,
				colours.orange,
				colours.magenta,
				colours.lightBlue,
				colours.yellow,
				colours.lime,
				colours.pink,
				colours.grey,
				colours.lightGrey,
				colours.cyan,
				colours.purple,
				colours.blue,
				colours.brown,
				colours.red,
				colours.green,
				colours.black
			}
			for i, c in ipairs(_colours) do
				local txt = ''
				if c == colours.white then
					txt = '##'
				end
				settings[k].Controls[i] = Button:Initialise(x, startY, 2, 1, c, colours.lightGrey, nil, nil, nil, function(self, x, y)
					OneOS.Settings:SetValue(k, c)
					return true
				end, txt)
				x = x + 2
			end
				

		elseif v.Type == 'Text' then
			settings[k].Control = TextBox:Initialise(controlX, startY, 23, 1, nil, value, nil, nil, function(self, key)
				OneOS.Settings:SetValue(k, self.TextInput.Value)
			end)
		elseif v.Type == 'Program' then
			local txt = value
			if not value then
				txt = 'None'
			else
				txt = Helpers.RemoveExtension(txt)
			end
			settings[k].Control = Button:Initialise(controlX, startY, nil, nil, colours.grey, colours.white, nil, nil, nil, function(self, x, y)
				local items = { 
					{
						Title = 'None',
						Click = function()
								OneOS.Settings:SetValue(k, nil)
								self.Text = "None"
								self.Width = #self.Text + 2
						end
					},
					{
						Separator = true
					}
				}

				for i, _v in ipairs(OneOS.FS.list('/Programs/')) do
					if Helpers.Extension(_v) == 'program' then
						table.insert(items, 
						{
							Title = Helpers.RemoveExtension(_v),
							Click = function()
								OneOS.Settings:SetValue(k, _v)
								self.Text = Helpers.RemoveExtension(_v)
								self.Width = #self.Text + 2
							end
						})
					end
				end

				Current.Menu = Menu:Initialise(x, y+1, nil, nil, self, items, true)
				return true
			end, txt)
		end
		startY = startY + 2
	end

	Update()
	EventHandler()
end

function Update()
	Draw()
	updateTimer = os.startTimer(1)
end

function Draw()
	Current.Clicks = {}
	Drawing.Clear(colours.white)

	Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, 3, colours.grey)
	Drawing.DrawCharacters(11, 2, 'OneOS', colours.lightGrey, colours.grey)
	Drawing.DrawCharacters(2, 2, 'Settings', colours.white, colours.grey)




	local startX = 2
	local startY = 5
	for k, v in pairs(settings) do
		Drawing.DrawCharacters(startX, startY, v.Label, colours.black, colours.white)
		if v.Control and v.Control.Draw then
			v.Control:Draw()
		elseif v.Controls then
			for i, c in ipairs(v.Controls) do
				c:Draw()
			end
		end
		startY = startY + 2
	end

	for i, elem in ipairs(InterfaceElements) do
		if elem.Draw then
			elem:Draw()
		end
	end
	if Current.Menu then
		Current.Menu:Draw()
	end

	Drawing.DrawBuffer()

	if Current.Input then
		term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
		term.setCursorBlink(true)
		term.setTextColour(Current.CursorColour)
	else
		term.setCursorBlink(false)
	end
end

MainDraw = Draw

function RegisterElement(elem)
	table.insert(InterfaceElements, elem)
end

function UnregisterElement(elem)
	for i, e in ipairs(InterfaceElements) do
		if elem == e then
			InterfaceElements[i] = nil
		end
	end
end

function RegisterClick(elem)
	table.insert(Current.Clicks, elem)
end

function CheckClick(object, x, y)
	local pos = GetAbsolutePosition(object)
	if pos.X <= x and pos.Y <= y and  pos.X + object.Width > x and pos.Y + object.Height > y then
		return true
	end
end

function DoClick(event, object, side, x, y)
	local pos = GetAbsolutePosition(object)
	if object and CheckClick(object, x, y) then
		return object:Click(side, x - pos.X + 1, y - pos.Y + 1)
	end	
end

function TryClick(event, side, x, y)
	local menu = Current.Menu

	if Current.Menu and DoClick(event, Current.Menu, side, x, y) then
		if menu == Current.Menu then
			Current.Menu = nil
		end
		Draw()
		return
	end

	for i, object in ipairs(Current.Clicks) do
		if DoClick(event, object, side, x, y) then
			if menu == Current.Menu then
				Current.Menu = nil
			end
			Draw()
			return
		end		
	end
	if Current.Menu then
		Current.Menu = nil
		Draw()
	end
end

function HandleKey(...)
	local args = {...}
	local event = args[1]
	local keychar = args[2]

	if Current.Input then
		if event == 'char' then
			Current.Input:Char(keychar)
		elseif event == 'key' then
			Current.Input:Key(keychar)
		end
	elseif keychar == keys.up then
		Scroll('mouse_scroll', -1)
	elseif keychar == keys.down then
		Scroll('mouse_scroll', 1)
	end
end

function GetAbsolutePosition(obj)
	if not obj.Parent then
		return {X = obj.X, Y = obj.Y}
	else
		local pos = GetAbsolutePosition(obj.Parent)
		local x = pos.X + obj.X - 1
		local y = pos.Y + obj.Y - 1
		return {X = x, Y = y}
	end
end

function EventRegister(event, func)
	if not Events[event] then
		Events[event] = {}
	end

	table.insert(Events[event], func)
end

function EventHandler()
	while true do
		local event = { coroutine.yield() }
		if Events[event[1]] then
			for i, e in ipairs(Events[event[1]]) do
				e(event[1], event[2], event[3], event[4], event[5])
			end
		end
	end
end

Initialise()