local floor = math.floor

local system_constructor = require("love_src.wrapper.Concord.system")
local audio = require("love_src.src.world.common.component.audio")
local animation = require("love_src.src.world.common.component.animation")

local system = {}

system.__index = system

system.pool = {
  pool = {
    audio.dict.sfx,
    animation.dict.anim_direction,
    animation.dict.fps,
    animation.dict.frame_i,
    animation.dict.image_frame,
    animation.dict.next_trigger_frame,
    animation.dict.run_time,
    animation.dict.trigger_frame,
  }
}

system.components = {
  [audio.dict.sfx] = audio.sfx,
  [animation.dict.anim_direction] = animation.anim_direction,
  [animation.dict.fps] = animation.fps,
  [animation.dict.frame_i] = animation.frame_i,
  [animation.dict.image_frame] = animation.image_frame,
  [animation.dict.next_trigger_frame] = animation.next_trigger_frame,
  [animation.dict.run_time] = animation.run_time,
  [animation.dict.trigger_frame] = animation.trigger_frame,
}

function system.new()
  local new_system = system_constructor.new("flip", system.pool)
  if (new_system) then
    for k, v in pairs(system) do
		  new_system[k] = v
	  end
    return new_system
  else
    return nil
  end
end

--- system frame
local function update_time(time, delta, indicator)
  return time + (delta * indicator)
end

local function get_loop(index, _max)
  local md = index % _max
  if (md == 0) then
    return _max
  else
    return index % _max
  end
end

local function update_fps_time(time, fps)
  -- floor time to 1. check x fps per second
  return floor(time / (1 / fps))
end

-- system trigger frame
local function is_trigger(trigger_frames, trigger_id, frame_id)
  return (trigger_frames[trigger_id] == frame_id)
end

function system:update(dt)
  for _, e in ipairs(self.pool) do
    e[animation.dict.run_time].data = update_time(
      e[animation.dict.run_time].data, dt, e[animation.dict.anim_direction].data
    )
    local new_index = update_fps_time(
      e[animation.dict.run_time].data, e[animation.dict.fps].data
    )
    e[animation.dict.frame_i].data = get_loop(
      new_index,
      #e[animation.dict.image_frame].data.images
    )

    if (is_trigger(
      e[animation.dict.trigger_frame].data,
      e[animation.dict.next_trigger_frame].data,
      e[animation.dict.frame_i].data
    )) then
      e[animation.dict.next_trigger_frame].data = get_loop(
        e[animation.dict.next_trigger_frame].data + 1, #e[animation.dict.trigger_frame].data
      )
      e[audio.dict.sfx].data.source:play()
    end
  end
end

return system
