--[[
  Checkout by Strannix
  
  Graffathon 2018 nonsense.
  
  TODO:
  * Tweens!
  - Next time?
    - Play with löve simplex noise
    - Play with löve math Transform
  * Audio timing with bpm? libraries for this?
    * Some but just fudge it this time
    * No CC-ND, check licence
  * Screen resolution independent drawing. Use canvas with push.lua again?
  * Hide mouse cursor
  * Neat font
  * Try the new text stuff
  * Seed random for consistent results!
  * Set filtering for sharp squares
  - Play with HSV colors?
    * https://love2d.org/wiki/HSV_color 
  * Fuse zip to exe -> copy /b love.exe+SuperGame.love SuperGame.exe
    * See https://love2d.org/wiki/Game_Distribution all needed junk
    * https://www.youtube.com/watch?v=WTk_HJdXVNQ
]]

local push = require "lib.push"
local Timer = require "lib.timer"

-- A relatively  small 16:9
VIRTUAL_WIDTH = 896
VIRTUAL_HEIGHT = 504

WINDOW_WIDTH, WINDOW_HEIGHT = love.graphics.getDimensions()

Phase = 0

function love.load()
  love.mouse.setVisible(false)
  -- Linear filtering for sharp squares!
  love.graphics.setDefaultFilter('linear', 'linear')
  push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT,
    {fullscreen = love.window.getFullscreen()})
  
  love.math.setRandomSeed(42)
  
  -- "Lewis and Dekalb" Kevin MacLeod (incompetech.com) 72 bpm	
  music = love.audio.newSource('data/Lewis_and_Dekalb.mp3', 'stream')
  music:play()
  
  -- Commodore 64 by  Devin Cook
  c64Font = love.graphics.newFont("data/Commodore_Angled-v1_2.ttf", 18)
  -- Barcode Text by Lasse Fister
  barcodeFont = love.graphics.newFont("data/LibreBarcode39Text-Regular.ttf", 78)
  
  title = {text = love.graphics.newText(barcodeFont, "checkout"), alpha = 0}
  spinner = {text = love.graphics.newText(c64Font, "Graffathon 2018"), rotation = 0, scale = 1, alpha = 1}
  
  done = function() 
    love.event.quit()
  end
  
  colorvalue = {r = 1, g = 1, b = 1, selected = 'r'}
  
  box = {x = 0, y = 0, size = 10 }

  beatbox = {
    x = VIRTUAL_WIDTH / 2,
    y = VIRTUAL_HEIGHT / 2,
    size = 10, linelenght = -30, randomrange = 0, remove_count = -50 
  }
  bpm = Round(60/72, 2)

  circle_explosion = { arc = 0, radius = 50, distance = 0, explode = false}

  endtext = "By Strannix"

  local grow, shrink, move, enter_beatbox, run_beatbox, last_effu, outro
  start = function()
    Timer.tween(2, title, {alpha = 1}, 'linear')
    Timer.tween(4, box, {x = VIRTUAL_WIDTH / 2, y = VIRTUAL_HEIGHT / 2}, 'in-out-quad', grow)
  end
  grow = function()
    Timer.tween(3, box, {size = 400}, 'linear', shrink)
  end
  shrink = function()
    Phase = 1
    Timer.tween(3, box, {size = 10}, 'linear', move)
    Timer.tween(5, spinner, {rotation = 10, scale = 5}, 'linear')
    Timer.tween(5, spinner, {alpha = 0}, 'in-cubic')
  end
  move = function()
    Timer.tween(2, box, {x = VIRTUAL_WIDTH, y = VIRTUAL_HEIGHT}, 'in-out-quad', enter_barcode)
  end
  enter_barcode = function()
    Phase = 2
    Timer.tween(5, beatbox, {linelenght = 30}, 'linear', run_beatbox)
  end

  run_beatbox = function()
    Timer.after(5, function()
      Timer.tween(5, beatbox, {randomrange = 1000}, 'in-quad')
    end)
    Timer.after(10, function()
      Timer.tween(2, beatbox, {remove_count = 100}, 'linear', last_effu)
    end)
    Timer.every(bpm, function()
        beatbox.size = 40
        Timer.tween(0.1, beatbox, {size = 10}, 'linear')
    end)
  end
  
  last_effu = function()
    Phase = 3
    
    Timer.tween(1, circle_explosion, {arc = 8}, 'out-quad', function() 
      Timer.tween(3, circle_explosion, {radius = 200}, 'in-out-cubic', function() 
        Timer.tween(1, circle_explosion, {radius = 0}, 'linear')
      end)
    end)
    
    Timer.after(4, function()
      circle_explosion.explode = true
      Timer.tween(5, circle_explosion, {distance = 1000}, 'linear', outro)
    end)
  end
  
  outro = function()
    Phase = 4
    
    Timer.tween(2, title, {alpha = 1}, 'linear')

    Timer.after(4, function() endtext = "Hey, there was a color" end)
    Timer.after(8, function() endtext = "Thanks Graffathon 2018" end)
    Timer.after(12, function() endtext = "This was fun" end)
    Timer.after(16, function() endtext = "Also fuck NVIDIA Optimus" end)
    
    Timer.after(20, done)
  end
  
  --Timer.after(bpm + 0.1, run_beatbox) -- whaterver, close enough..
  
  start()
  --last_effu()
  --outro()
end

function love.update(dt)
  Timer.update(dt)

  if love.keyboard.isDown( 'up' )then
    colorvalue[colorvalue.selected] = clamp(0, colorvalue[colorvalue.selected] + 0.01, 1)
  elseif love.keyboard.isDown( 'down' ) then
    colorvalue[colorvalue.selected] = clamp(0, colorvalue[colorvalue.selected] - 0.01, 1)
  end
end

function love.keypressed(key, scancode, isrepeat)
  if key == 'escape' then
    love.event.quit()
  end
  
  if key == '1' then
    colorvalue.selected = 'r'
  end
  if key == '2' then
    colorvalue.selected = 'g'
  end
  if key == '3' then
    colorvalue.selected = 'b'
  end
  
end


function love.draw()
  push:start()
  
  -- Default color
  love.graphics.setColor(1,1,1,1)
  
  if Phase == 0 then
    -- title fadein
    love.graphics.setColor(1,1,1, title.alpha)
    love.graphics.draw(title.text, (VIRTUAL_WIDTH / 2) - title.text:getWidth() / 2, 100)
  
    -- Default color
    love.graphics.setColor(1,1,1,1)
  
    -- moving box
    love.graphics.rectangle('fill', box.x - box.size / 2, box.y - box.size / 2, box.size, box.size)
  
    -- start/end boxes
    love.graphics.rectangle('fill', 0, 0, 10, 10)
    love.graphics.rectangle('fill', VIRTUAL_WIDTH - 10, VIRTUAL_HEIGHT - 10, 10, 10)
  
  elseif Phase == 1 then
    love.graphics.setColor(1,1,1, spinner.alpha)
    love.graphics.draw(spinner.text, VIRTUAL_WIDTH / 2, VIRTUAL_HEIGHT / 2, spinner.rotation,
      spinner.scale, spinner.scale, spinner.text:getWidth() / 2, spinner.text:getHeight() / 2)
  
    -- Default color
    love.graphics.setColor(1,1,1,1)
  
    -- moving box
    love.graphics.rectangle('fill', box.x - box.size / 2, box.y - box.size / 2, box.size, box.size)
    
    -- start/end boxes
    love.graphics.rectangle('fill', 0, 0, 10, 10)
    love.graphics.rectangle('fill', VIRTUAL_WIDTH - 10, VIRTUAL_HEIGHT - 10, 10, 10)

  
  elseif Phase == 2 then

    for i = -6, 6 do
      for j = -30,beatbox.linelenght do
  
        if beatbox.remove_count < i + j then
          modifier = love.math.random(-beatbox.randomrange, beatbox.randomrange)

          love.graphics.rectangle('fill', 
            (beatbox.x + i * 60) + modifier, beatbox.y + j * 10, beatbox.size, beatbox.size)
        end
      end
    end
    
  elseif Phase == 3 then 
    
    -- Red: 1, 0.3, 0.21
    love.graphics.setColor(1, 0.3, 0.21)
    
    love.graphics.arc('fill', VIRTUAL_WIDTH / 2, VIRTUAL_HEIGHT / 2,
      circle_explosion.radius, 0, circle_explosion.arc)
    
    if circle_explosion.explode then
      for i = 1,2000 do
        x, y = angle2Vec(VIRTUAL_WIDTH / 2, VIRTUAL_HEIGHT / 2, i, circle_explosion.distance + love.math.random(-40, 40))
        
        if love.math.random(0,1) == 1 then
        love.graphics.circle('fill', x, y, love.math.random(2, 5))
        else
        love.graphics.circle('line', x, y, love.math.random(2, 5))
        end
      end
    end
    
    
  elseif Phase == 4 then
    
    love.graphics.setColor(1,1,1, title.alpha)
    love.graphics.draw(title.text, (VIRTUAL_WIDTH / 2) - title.text:getWidth() / 2, 100)
    
    
    
    love.graphics.setFont(c64Font)
    love.graphics.printf(endtext, 0, 400, VIRTUAL_WIDTH, 'center')
    
    
  elseif Phase == 10 then -- Color selector
    
    
    love.graphics.setColor(colorvalue.r, colorvalue.g, colorvalue.b)
    -- moving box
    love.graphics.rectangle('fill', (VIRTUAL_WIDTH / 2) - 50, (VIRTUAL_HEIGHT / 2) - 50, 100, 100)
    
    love.graphics.setColor(1,1,1, 1)
    love.graphics.setFont(c64Font)
    love.graphics.printf(colorvalue.r .. ', ' .. colorvalue.g .. ', ' .. colorvalue.b,
      0, 400, VIRTUAL_WIDTH, 'center')
  end


  push:finish()
end

-- Round 'v' to 'p' decimal places
-- from Löve2D forums by emonk
function Round(v, p)
  -- figure out scaling factor for number of decimal points, or 0 if 'p' not supplied
  local scale = math.pow(10, p or 0);
  -- calculate result ignoring sign
  local res = math.floor(math.abs(v) * scale + 0.5) / scale;
  -- if 'v' was negative return value should be too
  if v < 0 then 
    res = -res; 
  end;
  -- return rounded value
  return res;
end;

-- Clamp value to range
-- from löve wiki
function clamp(min, val, max)
    return math.max(min, math.min(val, max));
end

DEGREES_TO_RADIANS = math.pi/180
function angle2Vec(startX, startY, angle, distance)
   angle = angle * DEGREES_TO_RADIANS
   return startX + math.cos(angle)*distance, startY + math.sin(angle)*distance
end