local tArgs = {...}
local l = fs.getDir(shell.getRunningProgram())
if not fs.exists(l.."/assets/mouse_white.limg") then
    printError("Assets not found")
    return
end
local function fread(file)
    local f = fs.open(file,"r")
    local r = f.readAll()
    f.close()
    return r
end
local mouseWhite = textutils.unserialize(fread(l.."/assets/mouse_white.limg"))[1]
local mouseBlack = textutils.unserialize(fread(l.."/assets/mouse_black.limg"))[1]
--local mouseDot = {{{"

local w,h = term.getSize()
local oTerm = term.current()
local buffer = window.create(term.current(),1,1,w,h,false)
local win = window.create(buffer,1,1,w,h,true)

local function getPixel(win,x,y)
    local w,h = win.getSize()
    if x < 1 or x > w or y < 1 or y > h then
  return "0","0","0"
    else
        theline = {win.getLine(y)}
        return string.sub(theline[1],x,x),string.sub(theline[2],x,x),string.sub(theline[3],x,x)
   end
end

local to_colors, to_blit = {}, {}
for i = 1, 16 do
    to_blit[2^(i-1)] = ("0123456789abcdef"):sub(i, i)
    to_colors[("0123456789abcdef"):sub(i, i)] = 2^(i-1)
end
 
 
 
local function toColor(theblit)
    return to_colors[theblit] or nil
end
 
 
 
local function toBlit(thecolor)
    return to_blit[thecolor] or nil
end
local function render(spr,x,y)
    local format = "lImg"
    _G.dBlit = {}
    if format == "lImg" then
        local sW,sH = #spr[1][1],#spr
        local w,h = term.getSize()
        for l=1,#spr do
        	if not y then
            	term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),(math.ceil(h/2)-math.floor(sH/2)+(l-1))+x)
            else
            	term.setCursorPos(x,y+(l-1))
            end
            local bl = {"","",""}
            bl[1] = spr[l][1]
            bl[2] = string.gsub(spr[l][2],"T"," ")
            bl[3] = string.gsub(spr[l][3],"T"," ")
            local b = {"","",""}
            --[[for t=1,#spr[l][1] do
            end]]
            
            for t=1,3 do
            	local cX = x-1
            	for le in string.gmatch(bl[t],".") do
            		cX = cX+1
            		if le == " " then
            			b[t] = b[t]..({getPixel(win,cX,y+(l-1))})[t]
            		else
            			b[t] = b[t]..le
            		end
            	end
            end
            _G.dBlit[l] = b
            term.blit(unpack(b))
        end
    elseif format == "nfp" or format == "nfg" then
        local b,e = string.find(spr,"\n")
        local sW,sH
        local w,h = term.getSize()
        local lines,sW = getLines(spr)
        sH = #lines
        for l=1,sH do
            term.setCursorPos(math.ceil(w/2)-math.floor(sW/2),math.ceil(h/2)-math.floor(sH/2)+(l-1))
            term.blit(string.rep(" ",#lines[l]),lines[l],lines[l])
        end
    end
end

local cor = coroutine.create(function() ok,err = pcall(shell.run,tArgs[1] or "shell") if not ok then printError(err) os.pullEvent("pranked") end end)
local mX,mY = 3,3
local moving = true
local mHold = false
local kHold = {}
local mouseDot = false
local tID = -1
local ks = {[keys.w]=true,[keys.a]=true,[keys.s]=true,[keys.d]=true}
while true do
	local e = {os.pullEventRaw()}
  if e[1] == "key" then
    kHold[e[2]] = true
  elseif e[1] == "key_up" then
    kHold[e[2]] = nil
  end
	local tDo = true
	term.redirect(win)
  if e[1] == "timer" and e[2] == tID then
    local setTimer = false
    if kHold[keys.w] then
      mY = mY-1
      setTimer = true
    end
    if kHold[keys.a] then
      mX = mX-1
      setTimer = true
    end
    if kHold[keys.s] then
      mY = mY+1
      setTimer = true
    end
    if kHold[keys.d] then
      mX = mX+1
      setTimer = true
    end
    if setTimer then
      tID = os.startTimer(0.1)
    end
	elseif e[1] == "key" and kHold[keys.leftCtrl] and e[2] == keys.k then
		moving = not moving
		tDo = false
  elseif e[1] == "key" and kHold[keys.leftCtrl] and e[2] == keys.m then
    mouseDot = not mouseDot
	elseif moving and (e[1] == "key" or e[1] == "key_up") then
		local ev = {["key_up"] = "mouse_up",["key"]="mouse_click"}
  local v = 1
  if kHold[keys.leftShift] then
      v = 2
  end
		if e[2] == keys.w then
			if e[1] == "key" then
				mY = mY-v
			end
			tDo = false
		elseif e[2] == keys.a then
			if e[1] == "key" then
				mX = mX-v
			end
			tDo = false
		elseif e[2] == keys.s then
			if e[1] == "key" then
				mY = mY+v
			end
			tDo = false
		elseif e[2] == keys.d then
			if e[1] == "key" then
				mX = mX+v
			end
			tDo = false
		elseif e[2] == keys.p then
      if e[1] == "key" then
        mHold = 1
        coroutine.resume(cor,ev[e[1]],1,mX,mY)
      else
        mHold = false
     		coroutine.resume(cor,ev[e[1]],1,mX,mY)
      end
			tDo = false
    elseif e[2] == keys.q then
      if e[1] == "key" then
        coroutine.resume(cor,"mouse_scroll",-1,mX,mY)
      end
      tDo = false
    elseif e[2] == keys.e then
      if e[1] == "key" then
        coroutine.resume(cor,"mouse_scroll",1,mX,mY)
      end
      tDo = false
		elseif e[2] == keys.o then
      if e[1] == "key" then
        mHold = 2
        coroutine.resume(cor,ev[e[1]],2,mX,mY)
      else
        mHold = false
        coroutine.resume(cor,ev[e[1]],2,mX,mY)
      end
      tDo = false
    end
    if ks[e[2]] and mHold then
      coroutine.resume(cor,"mouse_drag",mHold,mX,mY)
    end
	end

	local lookup = {w=true,s=true,a=true,d=true,q=true,e=true,j=true,o=true,p=true}
	for k,v in pairs(lookup) do
		lookup[string.upper(k)] = v
	end
	if tDo == true and not (moving and e[1] == "char" and lookup[e[2]]) then
		coroutine.resume(cor,unpack(e))
	end
	term.redirect(buffer)
	win.redraw()
  local cursor = {blink=win.getCursorBlink(),pos={win.getCursorPos()},color=win.getTextColor()}
	if moving then
		local mouse = mouseBlack
		if ({getPixel(win,mX,mY)})[3] == "0" then
			mouse = mouseWhite
		end
		if mouseDot then
      render({{"\7","e","T"}},mX,mY)
  else
      render(mouse,mX,mY)
  end
	end
	term.redirect(oTerm)
	buffer.setVisible(true)
	buffer.setVisible(false)
  if cursor.blink then
    term.setCursorPos(unpack(cursor.pos))
    term.setTextColor(cursor.color)
    term.setCursorBlink(true)
  else
    term.setCursorBlink(false)
  end
	--if moving then term.setTextColor(colors.red) else term.setTextColor(colors.white) end
end