local love = love
local scores = {}
local highScores = {}

local letters = { 
  letters = { "D",   "C",   "B",   "A",   "S",  "SS", "SSS" },
  ticks =   { 50000, 14400, 12000, 10000, 8000, 6000, 5000  },
  streaks = { 1,     20,    40,    60,    80,   100,  120   },
  score =   { 0,     5,     10,    22,    56,   150,  300   },
}

letters.letters[0] = "!"

local function ScoreToLetter( ticks, streak, score )
  local streakTier, ticksTier, scoreTier = 0, 0, 0
  
  for i, threshold in ipairs( letters.ticks ) do
    if ticks < threshold then ticksTier = i end
  end
  
  for i, threshold in ipairs( letters.streaks ) do
    if streak > threshold then streakTier = i end
  end
  
  for i, threshold in ipairs( letters.score ) do
    if score > threshold then scoreTier = i end
  end
  
  return letters.letters[ticksTier], letters.letters[streakTier], letters.letters[scoreTier] 
end

function scores.OnImpact( tick, isHitSuccessful )
  local score = 0
  if isHitSuccessful then
    scores.streak = scores.streak + 1
    scores.longestStreak = math.max( scores.streak, scores.longestStreak )
  else
    table.insert( scores.streaks, scores.streak)
    scores.streak = 0
  end

  for i, streak in ipairs( scores.streaks ) do
    score = score + math.pow( streak, 1.7 )
  end

  scores.score = score / ( ( tick / 120.0 ) - 36.0 )
  scores.t = tick
end

function scores.Reset()
  scores.score = 0
  scores.streak = 0
  scores.longestStreak = 0
  scores.highScore = scores.LoadHighScores()
  scores.streaks = {}
end

function scores.Get()
  return scores.score
end

function scores.Save()
  local i = 1
  for j = 1, #highScores do
    i = j
    if highScores[j] < scores.score then break end
  end
  table.insert( highScores, i )
  scores.highScore = math.max( scores.score, scores.highScore )
end

function scores.LoadHighScores()
  local gameList = assert( love.filesystem.getDirectoryItems( "demos" ) )
  local highScore = 0
  for i, name in ipairs( gameList ) do
    local s = love.filesystem.read( "demos/"..name, 64 )
    if ( s:len() > 32 ) then
      local gamescore, gameticks = love.data.unpack( "!16<dJ", s, 1)
      highScore = math.max( gamescore, highScore )
    end
  end
  return highScore
end

function scores.RenderHighScores()
  local wb = options["high contrast"].value and 0 or 1
  love.graphics.setColor( wb, wb, wb, 1 )
  local h = 1.0 * love.graphics.getFont():getHeight()
  local y = 0.5 * love.graphics.getHeight()
  
  local lTick, lStreak, lScore = ScoreToLetter( scores.t, scores.longestStreak, scores.score )
  love.graphics.printf(
    table.concat{
      "time: ",
      string.format("%.1f", scores.t / 120.0):gsub("%.", ","),
      ".",
      lTick,
      "\n",
      "streak: ",
      scores.longestStreak,
      ".",
      lStreak,
      "\n",
      "score: ",
      string.format("%.1f", scores.score ):gsub("%.", ","),
      ".",
      lScore,
      "\n",
      "record: ",
      string.format("%.1f", math.max( scores.highScore, scores.score )):gsub("%.", ","),
      ".!\n"
    },
    love.graphics.getWidth() * 0.5 - 250, y - 2 * h, 500, "justify" )
end

scores.highScore = scores.LoadHighScores()

return scores