local BaseMap   = require "core.modules.world.maps.parent"
local ShootMap  = BaseMap:extend()

local TILESIZE = 31
local TESTZONE = "forest"

local zoneDatas = require "datas.gamedata.maps.shoot.zones"

local Chunk = require "game.modules.world.maps.tools.chunk"

function ShootMap:new(world, maptype, mapname)
  ShootMap.super.new(self, world)

  self:setPadding(0, 0, 0, 0)
  self:getLevelData(mapname)
  self:generateTextures(self.datas.tiles, self.datas.background)
  self.layout = {}
  self.chunklist = {}

  self.width = 0
end

function ShootMap:updateWidth()
  self.size   = #self.layout * 8
  self.width  = self.size * 31
end

function ShootMap:getLevelData(mapname)
  local file  = file or "testlevel.test1"
  local level = require("datas.gamedata.maps.shoot." .. file)

  self.zone = level.datas.zone

  local currentZone_datas   = zoneDatas[self.zone]
  local bypass_data = level.datas.bypass_data

  self.datas = {}

  if (level.datas.bypass_zone) then
    self.datas.tiles      = bypass_data.tiles       or currentZone_datas.tiles
    self.datas.background = bypass_data.background  or currentZone_datas.background
  else
    self.datas = currentZone_datas
  end

  self.datas.layout = level.layout
  self.datas.parts  = level.parts
end

function ShootMap:loadCollisions()
  self:loadLayout();
  local w, h = self:getDimensions()
  --self.world:newCollision("floor", 0, 0, -16, w, h, 16)
  for i, chunkname in ipairs(self.layout) do

    self.chunklist[chunkname]:spawnGrounds((i-1)*31*8)
    self.chunklist[chunkname]:spawnObjects((i-1)*31*8)
  end

  local CHUNKSIZE = TILESIZE*8
  self.world:newCollision("fakefloor", -CHUNKSIZE, 0, -48, self.width+CHUNKSIZE*2, 200, 48)
end

function ShootMap:loadLayout()
  self.layout = {}
  -- [ShootMap].datas.layout est un tableau composée d'une série de tableau,
  -- chacuns en deux partie : le premier (part[1]) contient le nom du fichier
  -- où se trouve des partie de niveau, et la seconde partie (part[2]) une liste
  -- d'identifiant de partie de niveau à rajouter.

  -- Ce format permet de simplifier l'écriture de layout, si on a besoin de
  -- plusieur partie de niveau se trouvant dans le même fichier.
  for i, partContainer in ipairs(self.datas.layout) do
    for j, part in ipairs(partContainer[2]) do
      self:addPart(partContainer[1], part)
    end
  end
end

function ShootMap:addPart(source, partId)
  local source = source or "self"
  local partdata = {}

  -- On recupère les données de chunks

  -- Si le nom est "self", cela veut dire que fichier est le même que celui ou
  -- se trouve le layout, qui est forcément le fichier du niveau. Cela veut dire
  -- qu'il faut utiliser les parties de niveau du niveau actuel, localisée dans
  -- self.controller.parts
  if (source == "self") or (source == "") then
    partdata = self.datas.parts
  else
    -- Si c'est un autre nom, on charge dans "partdata" la liste des partie de niveau
    -- du fichier qu'on réfère.
    local chunkfile = require("datas.gamedata.maps.shoot.chunks." .. source)
    partdata = chunkfile.parts
  end

  local chunklist = partdata[partId]

  -- chunklist fonctionne de la même manière que partlist.
  -- chaque entrée dans la liste (chunkContainer) contient deux partie :
  -- chunkContainer[1]: l'identifiant du fichier où se trouve le chunk voulu
  -- chunkContainer[2]: la liste de chunks voulu. chaque entrée dedans est
  -- un nombre correspondant à un chunk
  for i, chunkContainer in ipairs(chunklist) do
    for j, chunk in ipairs(chunkContainer[2]) do
      self:addChunk(source, chunkContainer[1], chunk)
    end
  end

end

function ShootMap:addChunk(source, filename, chunkid)
  local filename = filename or "self"
  if (filename == "self") or (filename == "") then
    filename = source
  end

  local chunkfile = require("datas.gamedata.maps.shoot.chunks." .. filename)
  local chunkdata = chunkfile.chunks
  local chunkpos = #self.layout
  local chunkname = filename .. chunkid
  if self.chunklist[chunkname] == nil then
    self.chunklist[chunkname] = Chunk(self, chunkdata[chunkid])
  end
  table.insert(self.layout, chunkname)
  self:updateWidth()
end

function ShootMap:getChunk(id)
  return self.chunklist[self.layout[id]]
end

function ShootMap:addBlock(x, y, w, h, top, bottom)
  -- Empty Placeholder function
end

function ShootMap:getDimensions()
  return self.width, 100
end

function ShootMap:loadPlayers()
  self.world:addPlayer(16, 50, 0, 1)
end

function ShootMap:loadActors()
  -- Empty Placeholder function
end

function ShootMap:generateTextures(tile, background)

  self.texture = {}
  self.texture.floor  = self:generateFloor(tile)
  self.texture.border = love.graphics.newImage("assets/backgrounds/borders.png")
  self.quads = {}
  local w, h = self.texture.border:getDimensions()
  self.quads.borders = love.graphics.newQuad(0, tile*10, 80, 10, w, h)

  self:addParallax(background)
end

function ShootMap:generateFloor(tile)
  local canvas = love.graphics.newCanvas(31*16, 100)
  local tile    = tile or 1

  local tileTexture = love.graphics.newImage("assets/backgrounds/normaltile.png")
  local tileQuad    = {}
  local w, h  = tileTexture:getDimensions()
  tileQuad[1] = love.graphics.newQuad( 0, tile*24, 40, 24, w, h)
  tileQuad[2] = love.graphics.newQuad(40, tile*24, 40, 24, w, h)

  love.graphics.setCanvas( canvas )

  for i=1, 5 do
    for j=0, 18 do
      local tiley = (i-1)*20 - 4
      local tilex = (j-2)*31 + (i-1)*10
      local variant = 1 + ((i + j) % 2)
      love.graphics.draw(tileTexture,   tileQuad[variant], tilex, tiley)
    end
  end

  love.graphics.setCanvas( )

  local imagedata = canvas:newImageData()
  local texture   = love.graphics.newImage( imagedata )
  imagedata:release()
  canvas:release()
  return texture
end

function ShootMap:draw(x, y, w, h)
  self:drawChunks(x)
end

function ShootMap:addParallax(filename)
  -- Empty Placeholder function
  local filename    = filename or "forest"
  local backfolder  = "assets/backgrounds/parallax/"
  filename    = backfolder .. filename
  self.texture.back1  = love.graphics.newImage(filename .. "-back.png")
  self.texture.back2  = love.graphics.newImage(filename .. "-fore.png")
end

function ShootMap:drawParallax(x, y, w, h)

  self:drawBackground(x, y, w, h)
  self:drawForeground(x, y + 10, w, h)
  local w2, _ =  self.texture.floor:getDimensions()
  for i=1, 2 do
    local x2 = x % w2
    love.graphics.draw(self.texture.floor, ((i-1)*31*16)-x2, -y)
  end

  self:drawBorder(x, y + 10)
  self:drawBorder(x, y - 100)
end

function ShootMap:drawBackground(x, y, w, h)
  local w2, h2 = self.texture.back1:getDimensions()
  local imax = math.ceil(w / w2) + 1
  for i=1, imax do
    local x1 = (x / 5) % w2
    love.graphics.draw(self.texture.back1, (i-1)*w2 - x1, 0, 0, 1, 1, 0, 0)
  end
end

function ShootMap:drawForeground(x, y, w, h)
  local w2, h2 = self.texture.back2:getDimensions()
  local imax = math.ceil(w / w2) + 1
  for i=1, imax do
    local x1 = (x / 2) % w2
    love.graphics.draw(self.texture.back2, (i-1)*w2 - x1, -y, 0, 1, 1, 0, h2)
  end
end

function ShootMap:drawBorder(x, y)
  for i=1, 7 do
    local x2 = x % 80
    love.graphics.draw(self.texture.border, self.quads.borders, (i-1)*80 - x2, -y, 0, 1, 1)
  end
end

function ShootMap:drawCliff(x, y, w, h)
  local w2, h2 = self.texture.cliff:getDimensions()
  local imax = math.ceil(w / w2) + 1
  for i=1, imax do
    local x1 = (x) % w2
    love.graphics.draw(self.texture.cliff, (i-1)*w2 - x1, -y, 0, 1, 1, 0, 0)
  end
end

function ShootMap:drawChunks(x)
  local x = x or 0
  local firstChunk = math.floor(x / (8*31)) - 2

  for i=1, 6 do
    local chunkID = firstChunk + i
    local chunk = self:getChunk(chunkID)
    if (chunk ~= nil) then
      chunk:draw((chunkID-1) * (8*31))
    end
  end
end

return ShootMap
