--[[

	Rhythmblock - a graphical music player for CC: Tweaked
	(c) 2021 mint <they@mint.lgbt>

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <https://www.gnu.org/licenses/>.

--]]

-- Change these lines to change the GUI colors.
accentColor = colors.gray 
buttonColor = colors.lightGray
textColor = colors.lightGray
backgroundColor = colors.black

-- Code starts from here

function round(n) -- We need a function to round the center of the terminal
    return n % 1 >= 0.5 and math.ceil(n) or math.floor(n)
end
width, height = term.getSize() -- Gets the terminal size to determine the center
centerWidth = round(width / 2) -- Defines the horizontal center
centerHeight = round(height / 2) -- Defines the vertical center

if arg[1] == nil then
	peripherals = peripheral.getNames() -- Gets peripherals to check if any disk drives are available
	if #peripherals == 0 then
		term.setTextColor(colors.red)
		print("No drive")
		return false -- Exits if there's no disk drive
	else
		driveCount = 0
		for n = 1, #peripherals do
			local driveCheck = peripherals[n]
			if peripheral.getType(driveCheck) == "drive" then
				drive = driveCheck
				driveCount = driveCount + 1
			end
		end
		if driveCount > 1 then
			term.setTextColor(colors.red)
			print("Too many disk drives. Specify where the desired disk drive is located by running 'rhythmblock [drive position]'") -- For safety reasons
			return false	
		elseif driveCount == 0 then
			term.setTextColor(colors.red)
			print("No drive")
                	return false -- Exits if there's no disk drive
		end
	end
else
	drive = arg[1]
end

--[[ Instead of calling every status by string, we call the variables storing the strings. This may ease translation if we plan to do so in the future.
]]

defaultStatus = "Rhythmblock"
invalidFormatStatus = "Not a music disc"
noDiscStatus = "No disc"
noAudioStatus = "No audio is playing"
ejectText = "Eject"

function playDisc()
	term.clear()
	if disk.isPresent(drive) and disk.hasAudio(drive) then -- Determines if there's a disc or not and if it's a music disc
        	disk.playAudio(drive)
		buttonRender(true)
		playing = true
		status = disk.getAudioTitle(drive)
		buttonRender(true)
	elseif disk.isPresent(drive) then
        	status = invalidFormatStatus
		buttonRender(false)	
	else -- If none of these checks are passed then it just means there's no disc in the drive.
        	status = noDiscStatus
		buttonRender(false)
	end
end

function ejectDisc() -- Ejects the disc! How cool is that?
	term.clear()
	buttonRender(false)
	if playing then
		stopDisc()
		disk.eject(drive)
	elseif disk.isPresent(drive) then -- If there's a disc, it'll be ejected.
		disk.eject(drive)
	else -- If not it'll report there's no disc.
		status = noDiscStatus
	end
end

function stopDisc() -- Stops the music
	playing = false
	status = defaultStatus
	disk.stopAudio(drive)
	term.clear()
	buttonRender(false)
end

function renderPlayButton() -- Renders the Play button
	paintutils.drawFilledBox(centerWidth - 4, centerHeight - 4, centerWidth + 4, centerHeight + 2, accentColor)
	paintutils.drawFilledBox(centerWidth - 2, centerHeight - 3, centerWidth - 1, centerHeight + 1, buttonColor)
	paintutils.drawFilledBox(centerWidth, centerHeight - 2, centerWidth + 1, centerHeight, buttonColor)
	paintutils.drawPixel(centerWidth + 2, centerHeight - 1, buttonColor)
end


function renderStopButton() -- Renders the Stop button
        paintutils.drawFilledBox(centerWidth - 4, centerHeight - 4, centerWidth + 4, centerHeight + 2, accentColor)
        paintutils.drawFilledBox(centerWidth - 2, centerHeight - 3, centerWidth + 2, centerHeight + 1, buttonColor)
end

function renderEjectButton() -- Renders the Eject button
        paintutils.drawLine(centerWidth - 3, centerHeight + 4, centerWidth + 3, centerHeight + 4, accentColor)
	term.setTextColor(buttonColor)
	term.setCursorPos(centerWidth - 2, centerHeight + 4)
	term.write(ejectText)
end

function renderCloseButton() -- Renders the Close button
        term.setCursorPos(width - 1, 1)
        term.setTextColor(textColor)
        term.setBackgroundColor(backgroundColor)
        term.write(" x")
end

function buttonRender(play) -- Render some buttons depending if the computer is advanced or not
        if play then
                renderStopButton()
        else
                renderPlayButton()
        end
        if term.isColour() then
                renderEjectButton()
                renderCloseButton()
        end
end

function statusRender(s) -- Renders the status bar 
	term.setCursorPos(1, 1)
	term.setTextColor(textColor)
	term.setBackgroundColor(backgroundColor)
	term.write(s)
end

term.clear()
term.setBackgroundColor(backgroundColor) -- Setting the background color
buttonRender(false)
status = defaultStatus -- Setting the value to the default

while true do
    statusRender(status) -- Renders the status
    if term.isColour() then -- Renders the close button (if the song title is too long, the close button kind of disappears)
    	renderCloseButton()
    end
    local eventData = {os.pullEvent()}
    local event = eventData[1]
   
    if event == "mouse_up" then -- If the event triggered is the mouse clicking it'll do what's next
	if eventData[2] == 1 and eventData[3] >= centerWidth - 4 and eventData[4] >= centerHeight - 4 and eventData[3] <= centerWidth + 4 and eventData[4] <= centerHeight + 2 then -- If the user clicks on the play/stop button it'll begin playing the disc 
                if playing then
                        stopDisc()
                else
                        playDisc()
                end
        elseif eventData[2] == 1 and eventData[3] >= centerWidth - 2 and eventData[4] >= centerHeight + 4 and eventData[3] <= centerWidth + 2 and eventData[4] <= centerHeight + 4 then -- If the user clicks on the eject button it'll eject the disc 
                ejectDisc()
	elseif eventData[2] == 1 and eventData[3] == width and eventData[4] == 1 then -- If the user presses the X it'll quit
		stopDisc()
		term.clear()
                term.setCursorPos(1, 1)
                return true	
	end
    elseif event == "key_up" then -- Same order but now with keys
	local name = keys.getName(eventData[2]) or "unknown key"
    	if name == "space" then
                if playing then
                        stopDisc()
                else
                        playDisc()
                end
	elseif name == "e" then
		ejectDisc()
        elseif name == "q" then
		stopDisc()
		term.clear()
		term.setCursorPos(1, 1)
                return true
        end
    end
end
