local root = app.params["root"]
local assetDir = root .. "/public/assets"
local sourceDir = assetDir .. "/source"
app.fs.makeDirectory(root .. "/public")
app.fs.makeDirectory(assetDir)
app.fs.makeDirectory(sourceDir)

local C = {
  transparent = Color{ r=0, g=0, b=0, a=0 },
  grass = Color{ r=104, g=190, b=82, a=255 },
  grass2 = Color{ r=76, g=158, b=70, a=255 },
  cream = Color{ r=255, g=233, b=164, a=255 },
  honey = Color{ r=239, g=151, b=49, a=255 },
  orange = Color{ r=199, g=97, b=43, a=255 },
  sky = Color{ r=93, g=190, b=224, a=255 },
  water = Color{ r=68, g=171, b=216, a=255 },
  water2 = Color{ r=139, g=224, b=231, a=255 },
  stone = Color{ r=206, g=199, b=171, a=255 },
  stone2 = Color{ r=162, g=155, b=133, a=255 },
  brown = Color{ r=91, g=54, b=43, a=255 },
  wood = Color{ r=151, g=91, b=48, a=255 },
  leaf = Color{ r=51, g=130, b=60, a=255 },
  pink = Color{ r=237, g=111, b=150, a=255 },
  red = Color{ r=194, g=66, b=64, a=255 },
  white = Color{ r=247, g=244, b=226, a=255 },
  gray = Color{ r=194, g=199, b=199, a=255 },
  gray2 = Color{ r=132, g=142, b=145, a=255 },
  black = Color{ r=48, g=38, b=37, a=255 },
  yellow = Color{ r=255, g=213, b=62, a=255 },
  purple = Color{ r=133, g=89, b=159, a=255 },
}

local function fill(img, x, y, w, h, color)
  for yy = y, y + h - 1 do
    for xx = x, x + w - 1 do img:drawPixel(xx, yy, color) end
  end
end

local function pixel(img, x, y, color) img:drawPixel(x, y, color) end

local function outlineRect(img, x, y, w, h, color)
  fill(img, x, y, w, 1, color); fill(img, x, y+h-1, w, 1, color)
  fill(img, x, y, 1, h, color); fill(img, x+w-1, y, 1, h, color)
end

local function save(sprite, sourceName, pngName)
  sprite:saveAs(sourceDir .. "/" .. sourceName)
  sprite:saveCopyAs(assetDir .. "/" .. pngName)
  sprite:close()
end

local function makeTileset()
  local sprite = Sprite(256, 64, ColorMode.RGB)
  sprite.filename = "tileset"
  sprite.cels[1].image:clear(C.transparent)
  local img = sprite.cels[1].image
  local function tile(index, base)
    local x = (index % 16) * 16; local y = math.floor(index / 16) * 16
    fill(img, x, y, 16, 16, base)
    return x, y
  end

  for i=0,63 do
    local palette = {C.grass, C.stone, C.water, C.cream, C.wood, C.gray}
    local x,y = tile(i, palette[(i % #palette)+1])
    if i % 6 == 0 then
      pixel(img,x+3,y+5,C.grass2); pixel(img,x+11,y+3,C.cream); pixel(img,x+12,y+3,C.pink)
    elseif i % 6 == 1 then
      outlineRect(img,x+1,y+1,7,6,C.stone2); outlineRect(img,x+8,y+7,7,8,C.stone2)
    elseif i % 6 == 2 then
      fill(img,x,y+3,16,2,C.water2); fill(img,x+5,y+10,9,1,C.water2)
    elseif i % 6 == 3 then
      fill(img,x,y,16,4,C.honey); fill(img,x+2,y+7,4,3,C.orange); fill(img,x+10,y+6,4,4,C.orange)
    elseif i % 6 == 4 then
      fill(img,x,y+4,16,2,C.brown); fill(img,x+4,y,2,16,C.brown); fill(img,x+12,y,1,16,C.brown)
    else
      outlineRect(img,x+1,y+1,14,14,C.gray2); fill(img,x+3,y+3,10,10,C.white)
    end
  end

  local x,y = tile(0,C.grass); pixel(img,x+3,y+5,C.grass2); pixel(img,x+11,y+9,C.grass2)
  x,y = tile(1,C.stone); outlineRect(img,x,y,8,8,C.stone2); outlineRect(img,x+8,y+8,8,8,C.stone2)
  x,y = tile(2,C.water); fill(img,x,y+4,12,2,C.water2); fill(img,x+5,y+11,11,1,C.water2)
  x,y = tile(3,C.cream); fill(img,x,y,16,3,C.honey); fill(img,x,y+13,16,3,C.honey)
  x,y = tile(4,C.wood); fill(img,x,y+4,16,2,C.brown); fill(img,x,y+11,16,1,C.brown)
  x,y = tile(5,C.white); outlineRect(img,x,y,16,16,C.gray)
  x,y = tile(6,C.grass); fill(img,x+2,y+3,12,10,C.leaf); pixel(img,x+6,y+6,C.red); pixel(img,x+11,y+9,C.red)
  x,y = tile(7,C.grass); fill(img,x+1,y+2,14,12,C.leaf); fill(img,x+4,y+4,3,3,C.pink); fill(img,x+10,y+7,3,3,C.yellow)
  x,y = tile(8,C.honey); fill(img,x,y+6,16,10,C.cream); outlineRect(img,x,y+6,16,10,C.orange)
  x,y = tile(9,C.orange); fill(img,x,y+6,16,10,C.cream); fill(img,x+6,y+9,4,7,C.brown)
  x,y = tile(10,C.cream); fill(img,x+2,y+5,12,8,C.wood); outlineRect(img,x+2,y+5,12,8,C.brown)
  x,y = tile(11,C.grass); fill(img,x+6,y,4,16,C.wood); fill(img,x+1,y,14,8,C.leaf)
  x,y = tile(12,C.grass); fill(img,x+2,y+2,12,12,C.pink); fill(img,x+5,y+5,6,6,C.yellow)
  x,y = tile(13,C.wood); fill(img,x+4,y+2,8,14,C.black); fill(img,x+6,y+3,4,11,C.water)
  x,y = tile(14,C.sky); fill(img,x+4,y,8,16,C.white); fill(img,x+1,y+4,14,8,C.white)
  x,y = tile(15,C.white); fill(img,x,y,16,3,C.gray); fill(img,x,y+13,16,3,C.gray)
  x,y = tile(16,C.grass); fill(img,x+3,y+5,10,7,C.white); outlineRect(img,x+3,y+5,10,7,C.brown); pixel(img,x+8,y+8,C.red)
  save(sprite, "tileset.aseprite", "tileset.png")
end

local speciesColors = {C.cream,C.pink,C.brown,C.orange,C.gray,C.honey,C.grass2,C.purple,C.red,C.sky,C.yellow,C.wood,C.white}

local function drawCharacter(img, ox, oy, body, facing, step, expression, species)
  fill(img,ox,oy,16,24,C.transparent)
  local skin = body
  fill(img,ox+4,oy+3,8,8,skin)
  fill(img,ox+3,oy+5,10,5,skin)
  if species == "rabbit" then fill(img,ox+4,oy,2,5,skin); fill(img,ox+10,oy,2,5,skin) end
  if species == "deer" then pixel(img,ox+3,oy+2,C.brown); pixel(img,ox+12,oy+2,C.brown) end
  if species == "bird" then fill(img,ox+3,oy+6,10,8,skin); pixel(img,ox+13,oy+8,C.honey) end
  local eyeY = oy+6
  pixel(img,ox+6,eyeY,C.black); pixel(img,ox+10,eyeY + (expression == "off" and 1 or 0),C.black)
  if expression == "smile" then pixel(img,ox+7,oy+9,C.red); pixel(img,ox+8,oy+10,C.red); pixel(img,ox+9,oy+9,C.red)
  elseif expression == "flat" then fill(img,ox+7,oy+9,3,1,C.black)
  else pixel(img,ox+7,oy+9,C.black); fill(img,ox+8,oy+10,3,1,C.black) end
  fill(img,ox+4,oy+12,8,8,body)
  fill(img,ox+3,oy+13,2,6,C.cream); fill(img,ox+11,oy+13,2,6,C.cream)
  local foot = step % 2
  if facing == "left" or facing == "right" then
    fill(img,ox+4-foot,oy+20,3,3,C.black); fill(img,ox+9+foot,oy+20,3,3,C.black)
  else
    fill(img,ox+4+foot,oy+20,3,3,C.black); fill(img,ox+9-foot,oy+20,3,3,C.black)
  end
  if facing == "up" then fill(img,ox+5,oy+5,6,4,skin); fill(img,ox+5,oy+6,6,2,C.brown) end
  if facing == "left" then pixel(img,ox+5,eyeY,C.black); fill(img,ox+10,eyeY,2,2,skin) end
  if facing == "right" then pixel(img,ox+11,eyeY,C.black); fill(img,ox+4,eyeY,2,2,skin) end
end

local function makeCharacters()
  local cols, rows = 16, 4
  local sprite = Sprite(cols*16, rows*24, ColorMode.RGB)
  sprite.cels[1].image:clear(C.transparent)
  local img = sprite.cels[1].image
  local dirs = {"down","up","left","right"}
  for d=0,3 do for f=0,3 do drawCharacter(img,f*16,d*24,C.sky,dirs[d+1],f,"smile","human") end end
  local npc = {
    {C.honey,"dog"},{C.white,"rabbit"},{C.brown,"bear"},{C.orange,"cat"},
    {C.cream,"deer"},{C.sky,"bird"},{C.grass2,"turtle"}
  }
  for n=0,6 do for e=0,2 do
    local index = 16 + n*3 + e; local ox=(index%cols)*16; local oy=math.floor(index/cols)*24
    local exp=({"smile","flat","off"})[e+1]
    drawCharacter(img,ox,oy,npc[n+1][1],"down",0,exp,npc[n+1][2])
  end end
  for n=0,4 do
    local index=37+n; local ox=(index%cols)*16; local oy=math.floor(index/cols)*24
    drawCharacter(img,ox,oy,speciesColors[n+8],"down",n%2,"smile","human")
  end
  for n=0,3 do
    local index=42+n; local ox=(index%cols)*16; local oy=math.floor(index/cols)*24
    drawCharacter(img,ox,oy,(n%2==0 and C.pink or C.sky),"down",n%2,"smile","bird")
    if n%2==1 then fill(img,ox+7,oy+9,4,2,C.black) end
  end
  save(sprite,"characters.aseprite","characters.png")
end

local function drawPortrait(img, ox, body, expression, real)
  fill(img,ox,0,48,48,C.cream)
  fill(img,ox+7,6,34,34,C.brown)
  fill(img,ox+9,8,30,30,body)
  fill(img,ox+14,17,4,5,C.black); fill(img,ox+30,17 + (expression=="off" and 2 or 0),4,5,C.black)
  if real then
    fill(img,ox+15,31,18,2,C.black); fill(img,ox+13,13,8,2,C.gray2); fill(img,ox+27,13,8,2,C.gray2)
  elseif expression == "smile" then
    fill(img,ox+17,29,4,3,C.red); fill(img,ox+21,32,8,3,C.red); fill(img,ox+29,29,3,3,C.red)
  else fill(img,ox+18,30,14,2,C.black) end
end

local function makePortraits()
  local sprite=Sprite(9*48,48,ColorMode.RGB); sprite.cels[1].image:clear(C.transparent)
  local img=sprite.cels[1].image
  drawPortrait(img,0,C.sky,"smile",false); drawPortrait(img,48,C.gray,"flat",true)
  local colors={C.honey,C.white,C.brown,C.orange,C.cream,C.sky,C.grass2}
  for i=0,6 do drawPortrait(img,(i+2)*48,colors[i+1],"smile",false) end
  save(sprite,"portraits.aseprite","portraits.png")
end

makeTileset(); makeCharacters(); makePortraits()
print("Generated original Aseprite assets in " .. assetDir)
