local love = love
local passChimes = {}
local failChimes = {}
local drones = {}
local N = 8

love.audio.setDistanceModel( "exponentclamped" )

local function StartDrones()
  love.audio.setEffect( "droneReverb", {
      type = "reverb",
      volume = 1.0,
      decaytime = 20}

  )

  drones.bass = love.audio.newSource("sounds/drone.flac", "stream")  
  drones.alto = love.audio.newSource("sounds/drone.flac", "stream")
  drones.bass:setVolume( 0 )
  drones.bass:setPitch( 0.125 )
  drones.alto:setVolume( 0 )
  drones.bass:setPitch( 0.25 )
  drones.bass:setEffect( "droneReverb", true )
  drones.alto:setEffect( "droneReverb", true )
  drones.bass:stop()
  drones.alto:stop()

  love.audio.play( drones.bass )
  love.audio.play( drones.alto )
end

love.audio.setEffect( "passChimeReverb", {
    type = "reverb",
    volume = 1.0, } )

local passChime = love.audio.newSource("sounds/chimeb.flac", "static")
passChime:setEffect( "passChimeReverb", true )
local failChime = love.audio.newSource("sounds/chime.flac", "static")
failChime:setEffect( "passChimeReverb", true )

for i = 1, N do
  passChimes[i] = passChime:clone()
  failChimes[i] = failChime:clone()
end

local idxNextPassChime = 1
local idxNextFailChime = 1
local function GetNextPassChime( pass )
  idxNextPassChime = idxNextPassChime % N + 1
  return passChimes[ idxNextPassChime ]
end

local function GetNextFailChime( pass )
  idxNextFailChime = idxNextFailChime % N + 1
  return failChimes[ idxNextFailChime ]
end

local pitches = 
{
  1,
  2/3,
  3/2,
  9/8,
  27/16,
  81/64,
  243/128,
  2 --Safety
}

local function GetPitch( th )
  th = 0.5 + 0.5 * th / math.pi
  return pitches[ 1 + math.floor( th * 7 )]
end

local function OnImpact( impact, score, pass, level )

  --
  if not pass then
    --drones.bass:seek( level )
    -- drones.alto:seek( level )
  else
    
    love.audio.setEffect( "passChimeReverb", {
    type = "reverb",
    volume = 1.0, 
    gain = 0.1 + level / 200} )
    
  end

  local th = impact.th
  local r = impact.r

  -- Chimes 
  local chime = pass and GetNextPassChime() or GetNextFailChime()
  chime:setPitch( GetPitch( th ) )
  chime:setPosition( r * math.cos( th ), r * math.sin( th ) )
  chime:setVolume( 0.1 + level / 200 )
  local highgain = math.max( 0, math.min( score, 1.0 ) - (pass and 0.0 or 0.9))
  chime:setFilter{
    type = "lowpass",
    volume = 0.5 * impact.speed,
    highgain = highgain,
  }
  love.audio.stop( chime )
  love.audio.play( chime )

end

local function OnVictory( )
  love.audio.setEffect( "passChimeReverb", {
      type = "reverb",
      volume = 1.0,
      decaytime = 20,} )
  
    love.audio.setEffect( "droneReverb", {
      type = "reverb",
      volume = 1.0,
      decaytime = 20,} )
end

--score is the hypothetical "beat score" that would be attained
--if an impact took place at this instant.
local function Update( score, level )

  if level > 2 then
    drones.bass:setVolume( 0.5 * math.sqrt( score ) * (level / 120) )
    drones.alto:setVolume( 0.3 * score * ( level / 120 ))
  end

end

local function Reset( )
  for i = 1, N do
    love.audio.stop( passChimes[i] )
    love.audio.stop( failChimes[i] )
  end
  StartDrones()
end

Reset()
return { OnImpact = OnImpact, Update = Update, Reset = Reset, OnVictory = OnVictory}