local component = require("component")
local computer = require("computer")
local event = require("event")
local gpu = component.gpu
local os = require("os")
local unicode = require("unicode")

function resetGPU(w, h)
	gpu.setResolution(w, h)
	gpu.setBackground(0, false)
	gpu.setForeground(16777215, false)
	gpu.fill(1, 1, w, h, " ")
end

active = 1
function onKeyDown(name, addr, char, key, player)
	active = 0
	return false
end
event.listen("key_down", onKeyDown)

resetGPU(160, 50)
local ticks = 0

function getColor(ticks, mul)
	local ctr = ((ticks & 31) / 32) * 6
	local x = math.floor(mul * (ctr % 1))
	local y = mul
	local z = math.floor(mul * (1 - (ctr % 1)))
	if ctr >= 5 then
		return (y << 16) | z
    end
	if ctr >= 4 then
		return (x << 16) | y
    end
	if ctr >= 3 then
		return (z << 8) | y
    end
	if ctr >= 2 then
		return (y << 8) | x
    end
	if ctr >= 1 then
		return (z << 16) | (y << 8)
    end
	return (y << 16) | (x << 8)
end

local data = "WE ARE ALL CONNECTED"
local greets = "receiving data...          greetings: sangar * greaser * dss"

function getColorL(ticks, mul)
	local bp = math.floor((ticks >> 4) / 7)
	if bp >= #data then
		return 0xFF
	end
	if (ticks % 16) >= 11 then
		local x = mul
		local datapos = ticks >> 4
		local bitpos = datapos % 7
		local bytepos = math.floor(datapos / 7)
		local v = string.byte(data, bytepos + 1, bytepos + 1) >> bitpos
		if (v & 1) == 0 then
			x = x >> 2
		end
		return (x << 16) | (x << 8) | x
	end
	return getColorR(ticks, mul)
end

local lastSleep = computer.uptime()
function sleep(time)
	local target = lastSleep + time
	while computer.uptime() < target do
		os.sleep(0.05)
	end
	lastSleep = target
end

gpu.setBackground(0x999999, false)
gpu.setForeground(0xCCCCCC, false)
gpu.fill(1, 43, 160, 1, unicode.char(0x2580))
gpu.setBackground(0x444444, false)
gpu.setForeground(0x676767, false)
gpu.fill(1, 44, 160, 1, unicode.char(0x2580))
gpu.setBackground(0x333333, false)
gpu.fill(1, 45, 160, 6, " ")

local obarx = 80
local bary, baryh, baryd, barw, delta
local xd = 0
while active > 0 do
	bary = 1
	barh = 42
	baryd = 1
	barx = math.sin(ticks / 20) * math.cos(ticks / 40) * math.sin(ticks / 26.5)
	barx = barx * 80 + 80
	barw = 1
	delta = (barx - obarx)
	obarx = barx
	if delta < 0 then
		xd = 1
	elseif delta > 0 then
		xd = -1
	end
	if math.abs(delta) > 1 then
		if delta < 0 then
			delta = delta + 1
			barw = barw - delta
		else
			delta = delta - 1
			barx = barx - delta
			barw = barw + delta
		end
	end
	barx = barx - 1
	barw = barw + 2
	xd = xd * math.max(1, barw / 3)
	obarx = obarx + xd
	gpu.copy(1, bary, 160, barh - baryd, xd, baryd)
    gpu.setBackground(0, false)
	gpu.fill(1, bary, 160, baryd, " ")
	if xd < 0 then
  	  gpu.fill(160 + xd, bary, 160, barh, " ")      
    elseif xd > 0 then
  	  gpu.fill(1, bary, xd, barh, " ")      
    end
    gpu.setBackground(getColor(ticks, 0x9F), false)
    gpu.setForeground(getColor(ticks, 0xFF), false)
	if barw >= 5 then
		gpu.fill(barx - 2, bary, barw, barh, unicode.char(0x2591))
		gpu.fill(barx - 2 + (barw * 0.2), bary, barw * 0.6, barh, unicode.char(0x2593))
		gpu.fill(barx - 2 + (barw * 0.4), bary, barw * 0.2, barh, unicode.char(0x2588))
	else
		gpu.fill(barx - 2, bary, barw, barh, unicode.char(0x2593))
		gpu.fill(barx - 2 + 1, bary, barw * 0.34, barh, unicode.char(0x2588))
	end
	if ticks % 2 == 1 then
		sleep(0.05)
	end
	ticks = ticks + 1
end
resetGPU(80, 25)
