if lOS and lOS.started then
    error("LevelOS is already running, silly!")
end
changecolors = false
purecolors = false
local ranstartup = false
if purecolors == true then
    term.setPaletteColor(colors.white,1,1,1)
    term.setPaletteColor(colors.orange,1,0.5,0)
    -- magenta
    -- light blue
    term.setPaletteColor(colors.yellow,1,1,0)
    term.setPaletteColor(colors.lime,0,1,0)
    term.setPaletteColor(colors.pink,1,0.5,1)
    -- gray
    -- light gray
    term.setPaletteColor(colors.cyan,0,1,1)
    term.setPaletteColor(colors.purple,0.8,0,1)
    term.setPaletteColor(colors.blue,0,0,1)
    -- brown
    term.setPaletteColor(colors.green,0,0.6,0)
    term.setPaletteColor(colors.red,1,0,0)
    term.setPaletteColor(colors.black,0,0,0)
end
if changecolors == true then
    allcolors = {}
    for t=0,15,1 do
        allcolors[#allcolors+1] = {term.getPaletteColor(2^t)}
        term.setPaletteColor(2^t,0,0,0)
    end
end
_G.lOS = {started=false}
if fs.exists("LevelOS/data/settings.lconf") then
    local f = fs.open("LevelOS/data/settings.lconf","r")
    local s = f.readAll()
    f.close()
    lOS.settings = textutils.unserialize(s)
else
	lOS.settings = {maxAll=false} -- load from file usually
end
lOS.lMenu = false
lOS.log = ""
lOS.doasearch = false
lOS.notifications = {}
if fs.exists("AppData") == false then
    fs.makeDir("AppData")
end

if fs.exists("AppData") and fs.exists("AppData/Shapescape") and fs.exists("AppData/Shapescape/temp") then
	local f = fs.list("AppData/Shapescape/temp")
	for t=1,#f do
		fs.delete(fs.combine("AppData/Shapescape/temp",f[t]))
	end
end
lOS.oldterm = term.current()
local oldterm = lOS.oldterm

local w,h = term.getSize()
lOS.tskbr = window.create(oldterm,1,h-1,w,2,false)
term.redirect(lOS.tskbr)
shell.run("LevelOS/startup/MwMRender")
lOS.cvs = mwm.newCvs()
term.redirect(oldterm)
function lOS.tskbr.render()
    lOS.tskbr.setVisible(true)
    lOS.tskbr.setVisible(false)
end


local function log(txt)
    lOS.log = lOS.log..txt.."\n"
end


local hX,hY = 1,1
function lOS.getMousePos()
    return hX,hY
end

local tbPage = 1

function taskbargen(e)
    if e == nil then e = {} end
    local h = 2
    local width,height = oldterm.getSize()
    local tbSize = (width-15)/4
    lOS.cvs.clear()
    lOS.cvs.setColor(colors.gray)
    lOS.cvs.rect(1,h-1,w,2)
    term.setCursorPos(1,h-1)
    lOS.cvs.setColor(colors.white)
    lOS.cvs.write(string.char(144),1,h-1)
    lOS.cvs.write(string.char(141),1,h)
    local nextpage = false
    local temptable = {}
    local atable = {}
    for t=1,#lOS.processes do
        if lOS.processes[t].win ~= nil then
            atable[#atable+1] = lOS.processes[t]
        end
    end
    for t=1+(tbPage-1)*tbSize,tbPage*tbSize do
        if lOS.processes[t] ~= nil then
            if lOS.processes[t].win ~= nil and lOS.processes[t].winMode ~= "widget" then
                temptable[#temptable+1] = lOS.processes[t]
            end
        end
    end
    if #atable > tbPage*tbSize then
        log(tostring(#atable).." > ("..tbPage.."-1)*"..tbSize.." = "..((tbPage-1)*tbSize))
        nextpage = true
    end
    local val = #temptable
    if val > tbSize then
        val = tbSize
    end
    -- 1st page 1-9, second 10-18
    for t=1,val do
        log("Attempting to write icon "..t)
        if temptable[t] ~= nil then
            local win = temptable[t]
            if temptable[t] == lOS.wins[#lOS.wins] then
                lOS.cvs.setColor(colors.lightGray)
            else
                lOS.cvs.setColor(colors.gray)
            end
            if win.icon ~= nil then
                win.oIcon = lOS.cvs.rect(t*4,h-1,3,2,{tostring(lOS.oWins[t].icon[1]),tostring(lOS.oWins[t].icon[2])},colors.white)
            else
                --lOS.oWins[t].oIcon = lOS.cvs.rect(t*4,h-1,3,2,{"   "," "..t.." "},colors.white)
                --win.oIcon = lOS.cvs.rect(t*4,h-1,3,2,{"   "," "..string.sub(tostring(t),string.len(t),string.len(t)).." "},colors.white)
                win.oIcon = lOS.cvs.rect(t*4,h-1,3,2,{string.sub(win.title,1,3),string.sub(win.title,4,6)},colors.white)
            end
        end
    end
    --[[lOS.cvs.setColor(colors.lightGray)
    lOS.cvs.write(string.char(140),w-10,h-1)
    lOS.cvs.rect(w-9,h-1,1,1)
    lOS.cvs.setColor(colors.gray)
    lOS.cvs.write(string.char(155),w-9,h-1)
    lOS.cvs.setColor(colors.white)
    lOS.cvs.write(string.char(147)..string.char(148),w-10,h)
    lOS.cvs.setColor(colors.lightGray)
    lOS.cvs.write(string.char(149),w-8,h)]]
    lOS.cvs.setColor(colors.white)
    if nextpage == true then
        lOS.cvs.write("\30",w-12,h-1)
    end
    if tbPage > 1 then
        lOS.cvs.write("\31",w-12,h)
    end
    --lOS.cvs.write("Page "..tbPage,w-6,h)
    if not lOS.settings then lOS.settings = {} end
    if lOS.settings.timeOffset == nil then lOS.settings.timeOffset = 0 end
    if lOS.settings.rTime == nil then lOS.settings.rTime = false end
    local t = os.date("*t",os.epoch("local")/1000+lOS.settings.timeOffset*3600)
    local function tz(n)
    	return string.rep("0",2-string.len(n))..n
	end
    local txt = t.day.."-"..t.month.."-"..(t.year-2000)
	lOS.cvs.write(txt,w-(#txt-1),h)
    --lOS.timeDisplay = lOS.cvs.write(lTime,w-5,h-1)
    local lTime
    if lOS.settings.rTime then
        lTime = tz(t.hour)..":"..tz(t.min)
    else
        local nTime = math.mod(os.time()+lOS.settings.timeOffset,24)
    	local nHour = math.floor(nTime)
    	local nMinute = math.floor((nTime - nHour) * 60)
        lTime = tz(nHour)..":"..tz(nMinute)
    end
    lOS.timeDisplay = lOS.cvs.write(lTime,w-5,h-1)
    if e[1] == "mouse_up" then
        if e[3] >= width-6 and e[4] <= height and e[4] >= height-1 then
            lOS.execute("LevelOS/Clock.lua")
        elseif e[3] == width-12 and e[4] == height-1 and nextpage == true then
            tbPage = tbPage+1
            taskbargen()
        elseif e[3] == width-12 and e[4] == height and tbPage > 1 then
            tbPage = tbPage-1
            taskbargen()
        else
            for t=1,val do
                local win = temptable[t]
                if temptable[t] ~= nil then
                    if win.oIcon ~= nil and e[3] >= win.oIcon.x and e[4] >= height-1 and e[3] <= (win.oIcon.x-1)+win.oIcon.width and e[4] <= height then
                        local n = #lOS.wins
                        while lOS.wins[n] ~= nil do
                            if lOS.wins[n] == temptable[t] then
                                if n == #lOS.wins then
                                    table.remove(lOS.wins,n)
                                    local thing = -1
                                    while lOS.wins[thing] ~= nil do
                                        thing = thing-1
                                    end
                                    lOS.wins[thing] = temptable[t]
                                else
                                    if n < 0 then
                                        local abc = n-1
                                        lOS.wins[n] = nil
                                        while lOS.wins[abc] ~= nil do
                                            if lOS.wins[abc+1] == nil then
                                                lOS.wins[abc+1],lOS.wins[abc] = lOS.wins[abc],lOS.wins[abc+1]
                                                abc = abc-1
                                            end
                                        end
                                    else
                                        table.remove(lOS.wins,n)
                                    end
                                    lOS.wins[#lOS.wins+1] = temptable[t]
                                end
                                break
                            end
                            n = n-1
                        end
                    end
                end
            end
        end
    end
end

local function fread(file)
    local f = fs.open(file,"r")
    local o = f.readAll()
    f.close()
    return o
end

local wifi
if not fs.exists("LevelOS/assets/wifi.limg") then
    os.reboot()
else
    wifi = textutils.unserialize(fread("LevelOS/assets/wifi.limg"))
end

function taskbar(e)
    term.redirect(lOS.tskbr)
    lOS.cvs.clear()
    taskbargen(e)
    lOS.cvs.render()
    local w,h = term.getSize()
    term.setBackgroundColor(colors.gray)
    lUtils.renderImg(wifi[4-lOS.getInternet()],w-10,h-1)
    term.redirect(oldterm)
    lOS.tskbr.render()
end

lOS.processes = {}


lOS.noEvents = false


lOS.wins = {}

lOS.wAll = window.create(oldterm,1,1,w,h,false) -- window all (window object containing all window objects)
local wAll = lOS.wAll
lOS.depWin = window.create(wAll,1,1,w,h,false) -- window where windowless processes will draw objects to. (Does not get saved)

local proc = lOS.processes
proc[0] = {coroutine.create(function() shell.run("LevelOS/desktop.lua") end),title="Desktop",win=window.create(wAll,1,1,w,h-2,false),winMode="background"}

-- FOR DEBUGGING PURPOSES ONLY!!!!!
--proc[2] = {coroutine.create(function() shell.run("rom/programs/lua.lua") end),title="Lua",win=window.create(wAll,3,3,35,14,false),winMode="windowed"}
--proc[3] = {coroutine.create(function() shell.run("User/Scripts/log.lua") end),title="Log",win=window.create(wAll,5,5,35,14,false),winMode="windowed"}
--proc[3] = {coroutine.create(function() shell.run("rom/programs/shell.lua") end),title="Shell",win=window.create(wAll,7,7,35,14,false),winMode="windowed"}
--proc[4] = {coroutine.create(function() shell.run("rom/programs/shell.lua") end),win=window.create(wAll,1,1,51,17,false),winMode="borderless"}
--proc[4] = {coroutine.create(function() shell.run("rom/programs/shell.lua") end),title="Pastebin",win=window.create(wAll,9,9,35,14,false),winMode="borderless"}


function lOS.openShell()
    proc[#proc+1] = {coroutine.create(function() shell.run("rom/programs/shell.lua") end),title="Shell",win=window.create(wAll,7,7,35,14,false),winMode="windowed"}
    lOS.wins[#lOS.wins+1] = proc[#proc]
end

_G.wButton = 0

lOS.wins[0] = proc[0]
--lOS.wins[1] = proc[2]
--lOS.wins[2] = proc[3]
--lOS.wins[3] = proc[3]
--lOS.wins[4] = proc[4]
--table.insert(lOS.wins,1,proc[4])


for t=1,#lOS.wins do
    if lOS.wins[t].snap == nil then
        lOS.wins[t].snap = "none"
    end
end

shell.run("LevelOS/startup/lUtils")


local lTime = 0


local function system()
    local timer = 0
    os.sleep(2)
    lOS.execute("LevelOS/SystemUI.lua","background")
    while true do
        if #lOS.notifications > 0 then
            local w,h = term.getSize()
            -- use overlay API here
            timer = timer+0.1
            if timer >= 2 then
                table.remove(lOS.notifications,1)
                timer = 0
            end
        end
        os.sleep(0.1)
        lTime = lTime+0.02
    end
end



proc[1] = {coroutine.create(system),title="System",path="LevelOS/system.lua"}


local function getPixel(win,x,y)
    theline = {win.getLine(y)}
    return string.sub(theline[1],x,x),string.sub(theline[2],x,x),string.sub(theline[3],x,x)
end

local set = lOS.settings

local previewrect


--for p=0,#proc do
    --coroutine.resume(proc[p][1])
--end

coroutine.resume(proc[0][1])


local function new_execute(path,mode)


    local tPath = ""
    local rPath = string.sub(path,string.find(path,"%S+"))
    local b,e = string.find(path,"%S+")
    tPath = string.sub(path,e+2,string.len(path))
    local thingy = {}
    for i in string.gmatch(tPath,"%S+") do
        if i ~= nil and i ~= "" then
            thingy[#thingy+1] = i
        end
    end
    local program = path

    local w,h = oldterm.getSize()
    local thewin
    if w <= 60 or h < 21 or (set.maxAll == true) then
        thewin = window.create(oldterm,1,2,w,h-3,false)
    else
        thewin = window.create(oldterm,7,7,51,19,false)
    end
    local t = lUtils.getFileName(program)
    t = t:sub(1,1):upper()..t:sub(2)
    if mode == nil or mode ~= "background" then
        local tempthing = #lOS.wins+1
        lOS.processes[#lOS.processes+1] = {title=t,win=thewin,winMode="windowed",path=lUtils.getFilePath(program)}
        lOS.wins[tempthing] = lOS.processes[#lOS.processes]
        local function tempfunc()
            local a = {lOS.run(rPath,lOS.wins[tempthing],table.unpack(thingy))}
            if a[1] == false then
                local b = {lUtils.popup(fs.getName(rPath),fs.getName(rPath).." has stopped working.",25,9,{"OK","View Error"})}
                if b[3] == "View Error" then
                    lUtils.popup(fs.getName(rPath),a[2],25,11,{"OK"})
                end
            end
        end
        lOS.wins[tempthing][1] = coroutine.create(tempfunc)
        for i = 0, 15 do lOS.processes[#lOS.processes].win.setPaletteColor(2^i, lOS.wins[0].win.getPaletteColor(2^i)) end
    else
        lOS.processes[#lOS.processes+1] = {title=t,path=lUtils.getFilePath(program)}
        lOS.processes[#lOS.processes][1] = coroutine.create(function() lOS.run(rPath,lOS.processes[#lOS.processes],table.unpack(thingy)) end)
    end
end

local oldwin = {}

local function refreshProc(e)
    term.redirect(wAll)
    for i = 0, 15 do term.setPaletteColor(2^i, term.nativePaletteColor(2^i)) end
    if lOS ~= nil and lOS.execute ~= new_execute then
        lOS.execute = new_execute
    end
    local topwin
    for p=0,#proc do
        if proc[p].win ~= nil then
            if not proc[p].owin then
                proc[p].owin = proc[p].win
            end
            term.redirect(proc[p].owin)
        else
            term.redirect(lOS.depWin)
        end
        -- filter events
        local cWin
        local n = #lOS.wins
        while lOS.wins[n] ~= nil do
            if lOS.wins[n] == proc[p] then
                cWin = n
                break
            else
                n = n-1
            end
        end
        if proc[p].events and proc[p].events == "all" then
            if not (proc[p].sFilter and proc[p].sFilter ~= e[1]) then
                _,proc[p].sFilter = coroutine.resume(proc[p][1],table.unpack(e))
            end
        end
        if proc[p] == lOS.wins[#lOS.wins] or not (e[1] == "key" or e[1] == "key_up" or e[1] == "char" or e[1] == "paste" or e[1] == "terminate") then
            local a = lUtils.instantiate(e)
            if string.find(a[1],"mouse") and ((a[1] ~= "mouse_up" and a[1] ~= "mouse_drag") or proc[p] == lOS.wins[#lOS.wins]) and proc[p].win ~= nil and cWin >= 0 then
                local winX,winY = proc[p].win.getPosition()
                local winW,winH = proc[p].win.getSize()
                if (e[3] >= winX and e[4] >= winY and e[3] < winX+winW and e[4] < winY+winH) or (proc[p].winMode == "windowed" and e[3] >= winX-1 and e[4] >= winY-1 and e[3] < winX+winW+1 and e[4] < winY+winH+1) then -- actually it does work
                    if topwin == nil then
                        topwin = proc[p]
                        log("Process "..p.." selected.")
                        if not (e[3] >= winX and e[4] >= winY and e[3] < winX+winW and e[4] < winY+winH) then
                            topwin = nil
                        end
                    else
                        for b=0,#lOS.wins do
                            if lOS.wins[b] == proc[p] then
                                break
                            elseif lOS.wins[b] == topwin then
                                log("Process "..p.." selected.")
                                topwin = proc[p]
                                if not (e[3] >= winX and e[4] >= winY and e[3] < winX+winW and e[4] < winY+winH) then
                                    --lOS.notification("Detected border press! Topwin canceled.")
                                    topwin = nil
                                end
                                break
                            end
                        end
                    end
                elseif proc[p].winMode == "widget" and e[1] == "mouse_click" then
                    proc[p][1] = coroutine.create(function() return end)
                end
            elseif not string.find(a[1],"mouse") and not (lOS.noEvents and proc[p] == lOS.wins[#lOS.wins]) then
                if not (proc[p].events and proc[p].events == "all") then
                    if not (proc[p].sFilter and proc[p].sFilter ~= a[1]) then
                        _,proc[p].sFilter = coroutine.resume(proc[p][1],table.unpack(a))
                    end
                end
            end
        end
	if proc[p].win then
		proc[p].owin = term.current()
	end
    end
    if lOS.noEvents then
        topwin = nil
    end
    if topwin ~= nil then
        term.redirect(topwin.owin)
        local winX,winY = topwin.win.getPosition()
	if topwin.owin ~= topwin.win then
		local winX2,winY2 = topwin.owin.getPosition()
		winX = winX+(winX2-1)
		winY = winY+(winY2-1)
	end
        local winW,winH = topwin.owin.getSize()
        log("Attempting to update process...")
        local a = lUtils.instantiate(e)
        a[3] = a[3]-winX+1
        a[4] = a[4]-winY+1
        log("Event: "..table.concat(a,", "))
        if not (topwin.events and topwin.events == "all") then
            if not (topwin.sFilter and topwin.sFilter ~= a[1]) then
                _,topwin.sFilter = coroutine.resume(topwin[1],table.unpack(a))
                topwin.owin = term.current()
            elseif topwin.sFilter then
                term.redirect(wAll)
                term.setCursorPos(1,1)
                lUtils.transWrite(topwin.sFilter.." ~= "..a[1])
            end
        end
        log("Update complete.")
        if topwin.title ~= nil then
            --lOS.notification("You clicked on process "..topwin.title)
        end
    end
    log("wtf")
    for w=0,#lOS.wins do
        while lOS.wins[w] ~= nil and lOS.wins[w].win == nil do
            table.remove(lOS.wins,w)
        end
    end
    term.redirect(wAll)
    log("Starting window drawing...\n")
    --[[local twrite = term.write
    local tblit = term.blit
    function term.write(...)
        if ({term.getCursorPos()})[2] <= ({term.getSize()})[2] then
            return twrite(...)
        end
    end
    function term.blit(...)
        if ({term.getCursorPos()})[2] <= ({term.getSize()})[2] then
            return tblit(...)
        end
    end]]
    for w=0,#lOS.wins do
        log("Processing window "..w)
        local winW,winH = lOS.wins[w].win.getSize()
        local winX,winY = lOS.wins[w].win.getPosition()
        if w == #lOS.wins and previewrect ~= nil then
            term.setCursorPos(previewrect.x,previewrect.y)
            term.setTextColor(colors.lightBlue)
            for a=1,previewrect.w do
                term.setBackgroundColor(lUtils.toColor(({getPixel(wAll,previewrect.x+(a-1),previewrect.y)})[3]))
                term.write("\129")
            end
            for a=1,previewrect.h do
                term.setBackgroundColor(lUtils.toColor(({getPixel(wAll,previewrect.x,previewrect.y+(a-1))})[3]))
                term.setCursorPos(previewrect.x,previewrect.y+(a-1))
                term.write("\132")
                term.setBackgroundColor(lUtils.toColor(({getPixel(wAll,previewrect.x+(previewrect.w-1),previewrect.y+(a-1))})[3]))
                term.setCursorPos(previewrect.x+(previewrect.w-1),previewrect.y+(a-1))
                term.write("\136")
            end
            term.setCursorPos(previewrect.x,previewrect.y+(previewrect.h-1))
            for a=1,previewrect.w do
                term.setBackgroundColor(lUtils.toColor(({getPixel(wAll,previewrect.x+(a-1),previewrect.y+(previewrect.h-1))})[3]))
                term.write("\144")
            end
        end
        if lOS.wins[w].winMode == "background" then
            log("Drawing background window "..w)
            for l=1,winH do
                term.setCursorPos(1,l)
                term.blit(lOS.wins[w].win.getLine(l))
            end
        elseif lOS.wins[w].winMode == "borderless" or lOS.wins[w].winMode == "widget" then
            log("Drawing borderless window "..w.." from line "..(winY-winY+1).." to "..((winY+(winH-1))-winY+1))
            for l=winY,winY+(winH-1) do
                term.setCursorPos(winX,l)
                term.blit(lOS.wins[w].win.getLine(l-winY+1))
            end
        elseif lOS.wins[w].winMode == "windowed" then
            local width = winW+2
            local height = winH+2
            winX = winX-1
            winY = winY-1
            local bPos = 1
            --local w,h = wAll.getSize()
            local wW,wH = wAll.getSize()
            if (winX + (width-1)) > wW then
            --if lOS.wins[w].maximized == true then
                bPos = 0
            end
            local wincolor = colors.lightGray
            if w == #lOS.wins and not lOS.noEvents then
                wincolor = colors.gray
            end
            term.setBackgroundColor(wincolor)
            term.setCursorPos(winX,winY)
            for t=1,width-(10-bPos) do
                term.write(" ")
            end
            term.setTextColor(colors.white)
            if lOS.wins[w].resizable == nil then
                lOS.wins[w].resizable = true
            end
            term.setTextColor(colors.white)
            if w == #lOS.wins then
                if wButton == 1 then
                    term.setBackgroundColor(colors.lightGray)
                else
                    term.setBackgroundColor(wincolor)
                end
                term.write(" - ")
                if wButton == 2 then
                    term.setBackgroundColor(colors.lightGray)
                else
                    term.setBackgroundColor(wincolor)
                end
                if lOS.wins[w].resizable == false then
                    term.setTextColor(colors.lightGray)
                else
                    term.setTextColor(colors.white)
                end
                term.write(" + ")
                term.setTextColor(colors.white)
                if wButton == 3 then
                    term.setBackgroundColor(colors.red)
                else
                    term.setBackgroundColor(wincolor)
                end
                term.write(" × ")
                term.setBackgroundColor(wincolor)
            elseif maximisadumbass then
                term.setBackgroundColor(wincolor)
                term.setTextColor(colors.white)
                term.write(" - ")
                if lOS.wins[w].resizable == false then
                    term.setTextColor(colors.gray)
                else
                    term.setTextColor(colors.white)
                end
                term.write(" + ")
                term.setTextColor(colors.white)
                term.write(" × ")
            else
                term.setBackgroundColor(wincolor)
                term.setTextColor(colors.gray)
                term.write(" -  +  × ")
            end
            if bPos == 0 then
                term.write(" ")
            end
            term.setCursorPos(winX+1,winY)
            if lOS.wins[w].title ~= nil then
                term.write(lOS.wins[w].title)
            end
            term.setTextColor(wincolor)
            local progWin = lOS.wins[w].win
            for i=1,height-2 do
                term.setCursorPos(winX,winY+i)
                term.blit(string.char(149),lUtils.toBlit(wincolor),({getPixel(progWin,1,i)})[3])
                term.blit(progWin.getLine(i))
                term.blit(string.char(149),({getPixel(progWin,width-2,i)})[3],lUtils.toBlit(wincolor))
            end
            local bottomline = {string.char(138),({getPixel(progWin,1,height-2)})[3],lUtils.toBlit(wincolor)}
            for i=1,width-2 do
                bottomline[1] = bottomline[1]..string.char(143)
                bottomline[2] = bottomline[2]..({getPixel(progWin,i,height-2)})[3]
                bottomline[3] = bottomline[3]..lUtils.toBlit(wincolor)
            end
            bottomline[1] = bottomline[1]..string.char(133)
            bottomline[2] = bottomline[2]..({getPixel(progWin,width-2,height-2)})[3]
            bottomline[3] = bottomline[3]..lUtils.toBlit(wincolor)
            term.setCursorPos(winX,winY+(height-1))
            term.blit(table.unpack(bottomline))
        else
            log("Something went wrong with window "..w)
        end
    end
    for w=0,#proc do
        if proc[w].env ~= nil and proc[w].env.LevelOS ~= nil and proc[w].env.LevelOS.overlay ~= nil then
            coroutine.resume(coroutine.create(proc[w].env.LevelOS.overlay))
        end
    end
    local w,h = term.getSize()
    if #lOS.notifications > 0 then
        term.setBackgroundColor(colors.orange)
        term.setTextColor(colors.white)
        lUtils.textbox(lOS.notifications[1].txt,w-20,h-7,w,h-5)
    end
    if ({term.getCursorPos()})[2] <= ({term.getSize()})[2] then
        term.setCursorPos(1,1)
    end
    term.redirect(oldterm)
    for i = 0, 15 do term.setPaletteColor(2^i, lOS.wins[#lOS.wins].win.getPaletteColor(2^i)) end
    --local w,h = oldterm.getSize()
    --term.setBackgroundColor(colors.orange)
    --term.setTextColor(colors.white)
    --lOS.boxClear(w-20,h-7,w,h-5)
    --term.setCursorPos(w-19,h-6)
    --term.write(textutils.serialize(lOS.wins))
    --term.write("Yooo")
    --term.redirect(oldterm)
    for l=1,({wAll.getSize()})[2]-2 do
        if oldwin[l] == nil or lUtils.compare(oldwin[l],{wAll.getLine(l)}) == false then
            term.setCursorPos(1,l)
            term.blit(wAll.getLine(l))
        end
    end
    for t=1,h do
        oldwin[t] = {wAll.getLine(t)}
    end
    --term.setCursorPos(1,1)
    --term.setBackgroundColor(colors.black)
    --term.setTextColor(colors.white)
    --write(lOS.log)
    taskbar(e)
    for i = 0, 15 do term.setPaletteColor(2^i, term.nativePaletteColor(2^i)) end
end

local holding = {}

if lUtils then
    lUtils.isHolding = nil
end



local function manage()
    if ranstartup == false then
        local sProgs = fs.list("LevelOS/startup")
        for t=1,#sProgs do
            if sProgs[t] ~= "lUtils" and not string.find(sProgs[t],"updater") then
                --print("Running "..sProgs[t].."...")
                new_execute(fs.combine("LevelOS/startup",sProgs[t]),"background")
            end
        end
        ranstartup = true
    end
    if lUtils ~= nil and lUtils.isHolding == nil then
        function lUtils.isHolding(key)
            if type(key) == "string" then
                key = keys[key]
            end
            if holding[key] == nil or holding[key] == false then
                return false
            else
                return true
            end
        end
    end
    local dragging
    local dragon = false -- i can not come up with more variable names ffs
    local dragSide
    local dragX,dragY = false,false
    local DRx,DRy
    local OGw,OGh
    local OGx,OGy
    while true do
        local tempX,tempY = lOS.wins[#lOS.wins].win.getPosition()
	local tempX2,tempY2 = (tempX-1)+({lOS.wins[#lOS.wins].win.getCursorPos()})[1],(tempY-1)+({lOS.wins[#lOS.wins].win.getCursorPos()})[2]
	if tempY2 <= ({term.getSize()})[2] then	
            lOS.wins[#lOS.wins].win.restoreCursor()
            term.setCursorBlink(lOS.wins[#lOS.wins].win.getCursorBlink())
            term.setCursorPos(tempX2,tempY2)
            term.setTextColor(lOS.wins[#lOS.wins].win.getTextColor())
        end
        for t=1,#lOS.processes do
            if coroutine.status(lOS.processes[t][1]) == "dead" then
                for n=1,#lOS.wins do
                    if lOS.wins[n] == lOS.processes[t] then
                        table.remove(lOS.wins,n)
                        break
                    end
                end
                table.remove(lOS.processes,t)
                break
            end
        end
        for i = 0, 15 do term.setPaletteColor(2^i, lOS.wins[#lOS.wins].win.getPaletteColor(2^i)) end
        local e = {os.pullEventRaw()}
	if e[1] == "paste" and e[2] == " " then
		e[2] = ""
	end
        if e[1] == "key" then
            holding[e[2]] = true
        elseif e[1] == "key_up" then
            holding[e[2]] = false
            if holding[keys.leftCtrl] == true then
                if e[2] == keys.tab and #lOS.wins >= 2 then
                    lOS.wins[#lOS.wins-1],lOS.wins[#lOS.wins] = lOS.wins[#lOS.wins],lOS.wins[#lOS.wins-1]
                elseif e[2] == keys.w then
                    for i=1,#proc do
                        if lOS.wins[#lOS.wins] == proc[i] then
                            table.remove(proc,i)
                        end
                    end
                    table.remove(lOS.wins,#lOS.wins)
                end
            end
        end
        --for i = 0, 15 do term.setPaletteColor(2^i, term.nativePaletteColor(2^i)) end
        if e[1] == "mouse_move" then
            hX,hY = e[3],e[4]
        end
        local tempW,tempH = term.getSize()
        if string.find(e[1],"mouse") and (e[3] ~= nil) and not lOS.noEvents then
            local focusWin = 0
            for t=1,#lOS.wins do
                local winX,winY = lOS.wins[t].win.getPosition()
                local winW,winH = lOS.wins[t].win.getSize()
                local w,h = wAll.getSize()
                if not (winY == 2 or winX == 1) then
                    local change = false
                    if winW >= w then
                        winW = w-4
                        change = true
                    end
                    if winH >= h-3 then
                        winH = h-7
                        change = true
                    end
                    if change == true then
			os.queueEvent("term_resize")
                        lOS.wins[t].win.reposition(winX,winY,winW,winH)
                    end
                end
                if (e[3] >= winX and e[4] >= winY and e[3] < winX+winW and e[4] < winY+winH) or (lOS.wins[t].winMode == "windowed" and e[3] >= winX-1 and e[4] >= winY-1 and e[3] < winX+winW+1 and e[4] < winY+winH+1) then -- fixed
                    focusWin = t
                end
            end
            local bPos = 1
            local tempwin = lOS.wins[focusWin]
            local winX,winY = tempwin.win.getPosition()
            local winW,winH = tempwin.win.getSize()
            if tempwin.maximized ~= nil and tempwin.maximized == true then
                bPos = 0
            end
            if e[1] == "mouse_click" and focusWin > 0 and focusWin ~= #lOS.wins then
                table.remove(lOS.wins,focusWin)
                lOS.wins[#lOS.wins+1] = tempwin
            end
            if e[1] == "mouse_drag" and dragging ~= nil then
                local winX,winY = dragging.win.getPosition()
                local winW,winH = dragging.win.getSize()
                if dragon == true then
                    winX = OGx-(DRx-e[3])
                    winY = OGy-(DRy-e[4])
                    local w,h = wAll.getSize()


                    -- ALL THE RIGHT SIDE STUFF IS TEMP, TO SEE WHAT POSITION IT SHOULD BE ON. IT SHOULD BE RELATIVE TO THE SIZE OF A POTENTIAL LEFT SIDE SPLITSCREENED WINDOW

                    if e[3] == w and e[4] == 1 then
                        previewrect = {x=math.ceil(w/2)+1,y=2,w=math.floor(w/2)-1,h=math.floor((h-2)/2)-2}
                    elseif e[3] == w and e[4] == h-2 then
                        previewrect = {x=math.ceil(w/2)+1,y=math.floor((h-2)/2)+2,w=math.floor(w/2)-1,h=math.floor((h-2)/2)-2}
                    elseif e[3] == w then
                        previewrect = {x=math.ceil(w/2)+1,y=2,w=math.floor(w/2)-1,h=h-4}


                    elseif e[3] == 1 and e[4] == 1 then
                        previewrect = {x=2,y=2,w=math.floor(w/2)-2,h=math.floor((h-2)/2)-2}
                    elseif e[3] == 1 and e[4] == h-2 then
                        previewrect = {x=2,y=math.floor((h-2)/2)+2,w=math.floor(w/2)-2,h=math.floor((h-2)/2)-2}
                    elseif e[3] == 1 then
                        previewrect = {x=2,y=2,w=math.floor(w/2)-2,h=h-4}
                    elseif e[4] == 1 then
                        --previewrect = {x=2,y=2,w=w-2,h=h-4}
                    else
                        previewrect = nil
                    end
                end
                if dragX == true then
                    if dragSide == 1 then
			if OGw+(DRx-e[3]) >= 10 then
	                        winW = OGw+(DRx-e[3])
				winX = OGx-(DRx-e[3])
			end
                    else
			if OGw-(DRx-e[3]) >= 10 then
	                        winW = OGw-(DRx-e[3])
			end
                    end
                end
                if dragY == true then
			if OGh-(DRy-e[4]) >= 4 then
	                    winH = OGh-(DRy-e[4])
			end
                end
                dragging.win.reposition(winX,winY,winW,winH)
		os.queueEvent("term_resize")
            end
            local winX,winY = tempwin.win.getPosition()
            local winW,winH = tempwin.win.getSize()
            if focusWin > 0 then
                if tempwin.winMode == "windowed" and (e[1] == "mouse_click" or e[1] == "mouse_up") then
                    if e[4] == winY-1 then
                        if e[3] <= bPos+winX+winW-1 and e[3] >= bPos+winX+winW-3 then
                            if e[1] == "mouse_click" then
                                wButton = 3
                            else
                                log("Goodbye.")
                                for i=1,#proc do
                                    if lOS.wins[focusWin] == proc[i] then
                                        table.remove(proc,i)
                                    end
                                end
                                table.remove(lOS.wins,focusWin)
                            end
                        elseif e[3] <= bPos+winX+winW-4 and e[3] >= bPos+winX+winW-6 then
                            if e[1] == "mouse_click" then
                                wButton = 2
                            elseif (tempwin.resizable == nil or tempwin.resizable == true) then
                                tempwin.win.reposition(1,2,w,h-3)
                                os.queueEvent("term_resize")
                            end
                        elseif e[3] <= bPos+winX+winW-7 and e[3] >= bPos+winX+winW-9 then
                            if e[1] == "mouse_click" then
                                wButton = 1
                            else
                                --oop im dumb
                                local n=-1
                                while lOS.wins[n] ~= nil do
                                    n = n-1
                                end
                                lOS.wins[n] = tempwin
                                lOS.wins[#lOS.wins] = nil
                                -- plz work
                            end
                        elseif e[1] == "mouse_click" then
                            dragging = tempwin
                            dragon = true
                            DRx,DRy = e[3],e[4]
                            OGx,OGy = winX,winY
                        end
                    end
                    if e[4] >= winY and e[4] <= winY+winH and (e[3] == winX-1 or e[3] == winX+winW) and e[1] == "mouse_click" and (tempwin.resizable == nil or tempwin.resizable == true) then
                        dragging = tempwin
                        DRx = e[3]
                        OGw = winW
                        OGx = winX
                        dragX = true
                        if e[3] == winX-1 then
                            dragSide = 1
                        else
                            dragSide = 2
                        end
                    end
                    if e[4] == winY+(winH) and e[3] >= winX-1 and e[3] <= winX+(winW) and e[1] == "mouse_click" and (tempwin.resizable == nil or tempwin.resizable == true) then
                        dragY = true
                        DRy = e[4]
                        OGh = winH
                        dragging = tempwin
                    end
                end
            end
            if e[1] == "mouse_up" then
                if dragon == true then
                    local w,h = wAll.getSize()
                    if e[3] == w and e[4] == 1 then
                        dragging.win.reposition(math.ceil(w/2)+1,2,math.floor(w/2),math.floor((h-2)/2)-2)
                        -- whenever im not super lazy, make this window 1 pixel higher on the bottom and then don't draw the bottom line. that way it connects nicely to the window below.
                    elseif e[3] == w and e[4] == h-2 then
                        dragging.win.reposition(math.ceil(w/2)+1,math.floor((h-2)/2)+2,math.floor(w/2),math.floor((h-2)/2)-1)
                    elseif e[3] == w then
                        dragging.win.reposition(math.ceil(w/2)+1,2,math.floor(w/2),h-3)
                    elseif e[3] == 1 and e[4] == 1 then
                        dragging.win.reposition(1,2,math.floor(w/2)-1,math.floor((h-2)/2)-2)
                    elseif e[3] == 1 and e[4] == h-2 then
                        dragging.win.reposition(1,math.floor((h-2)/2)+2,math.floor(w/2)-1,math.floor((h-2)/2)-1)
                    elseif e[3] == 1 then
                        dragging.win.reposition(1,2,math.floor(w/2)-1,h-3)
                    elseif e[4] == 1 then
                        --dragging.win.reposition(1,2,w,h-3)
                    end
		    os.queueEvent("term_resize")
                end
                previewrect = nil
                dragon = false
                dragging = nil
                dragX,dragY = false,false
                wButton = 0
            end
        end
        if e[1] ~= "mouse_move" or e[3] ~= nil then
            refreshProc(e)
        end
    end
end




local hover = false
function lOS.isHover()
    return hover
end



local function hoverevent()
    local timerID = os.startTimer(3)
    while true do
        e = {os.pullEvent("mouse_move")}
        if e[1] == "mouse_move" then
            os.cancelTimer(timerID)
            timerID = os.startTimer(3)
            hX,hY = e[3],e[4]
            hover = false
        elseif e[1] == "timer" and e[2] == timerID then
            os.queueEvent("mouse_hover",1,hX,hY)
            log("Hovering at "..hX..","..hY)
            hover = true
        end
    end
end
function lOS.notification(txt)
    lOS.notifications[#lOS.notifications+1] = {txt=txt}
end
--parallel.waitForAny(manage,notifications,hoverevent)
manage()