A slate to write and draw on, then export to html
base64 = require('base64')

function export(filename)
  local outfile = io.open(filename, 'w')
  if outfile == nil then
    error('failed to create "'..filename)
  end
  for _,line in ipairs(Editor_state.lines) do
    if line.mode == 'drawing' then
      local svg_contents = export_drawing(line)
      outfile:write('<img src="data:image/svg+xml;base64,'..base64.encode(svg_contents)..'"/>')
    else
      outfile:write(line.data)
    end
    outfile:write('<br/>\n')
  end
  outfile:close()
end

function export_drawing(drawing)
  local out = {}
  table.insert(out, '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="256" height="128">\n')
  for _,shape in ipairs(drawing.shapes) do
    if shape.mode == 'freehand' then
      export_freehand(shape, out)
    elseif shape.mode == 'line' or shape.mode == 'manhattan' then
      export_line(drawing, shape, out)
    elseif shape.mode == 'polygon' or shape.mode == 'rectangle' or shape.mode == 'square' then
      export_polygon(drawing, shape, out)
    elseif shape.mode == 'circle' then
      export_circle(drawing, shape, out)
    elseif shape.mode == 'arc' then
      export_circle_arc(drawing, shape, out)
    elseif shape.mode == 'deleted' then
      -- ignore
    else
      assert(false, ('unknown drawing mode %s'):format(shape.mode))
    end
    table.insert(out, '\n')
  end
  table.insert(out, '</svg>\n')
  return table.concat(out)
end

function file_exists(filename)
  local f = io.open(filename)
  if f then
    f:close()
    return true
  end
  return false
end

function export_freehand(shape, out)
  table.insert(out, ('<path stroke="black" fill="none" d="M %d %d L'):format(shape.points[1].x, shape.points[1].y))
  for i=2,#shape.points do
    table.insert(out, (' %d %d'):format(shape.points[i].x, shape.points[i].y))
  end
  table.insert(out, '"/>\n')
end

function export_line(drawing, shape, out)
  local p1 = drawing.points[shape.p1]
  local p2 = drawing.points[shape.p2]
  table.insert(out, ('<line stroke="black" x1="%d" y1="%d" x2="%d" y2="%d"/>\n'):format(p1.x, p1.y, p2.x, p2.y))
  export_point(p1, out)
  export_point(p2, out)
end

function export_polygon(drawing, shape, out)
  table.insert(out, '<polygon stroke="black" fill="none" points="')
  for _,p in ipairs(shape.vertices) do
    local vertex = drawing.points[p]
    table.insert(out, ('%d,%d, '):format(vertex.x, vertex.y))
  end
  table.insert(out, '"/>\n')
  for _,p in ipairs(shape.vertices) do
    export_point(drawing.points[p], out)
  end
end

function export_circle(drawing, shape, out)
  local center = drawing.points[shape.center]
  table.insert(out, ('<circle stroke="black" fill="none" cx="%d" cy="%d" r="%d"/>\n'):format(center.x, center.y, shape.radius))
  export_point(center, out)
end

function export_circle_arc(drawing, shape, out)
  local center = drawing.points[shape.center]
  local cx,cy = center.x, center.y
  -- angle 0
  local zx,zy = cx+shape.radius, cy
  local sx,sy = geom.rotate(cx,cy, zx,zy, shape.start_angle)
  local ex,ey = geom.rotate(cx,cy, zx,zy, shape.end_angle)
  local sweep_flag = 0
  if shape.start_angle < shape.end_angle then
    sweep_flag = 1
  end
  table.insert(out, ('<path stroke="black" fill="none" d="M %d %d A %d,%d 0 0 %d %d,%d"/>'):format(sx,sy, shape.radius,shape.radius, sweep_flag, ex,ey))
  export_point(center, out)
end

function export_point(p, out)
  table.insert(out, ('<circle cx="%d" cy="%d" r="1"/>\n'):format(p.x, p.y))
  if p.name then
    -- couple of adjustments:
    -- * lines.love text coordinate starts at top left, but SVG starts at baseline.
    --
    -- * lines.love renders labels at x,y both offset by 5px on the screen.
    --   While rendering SVG, however, we don't have pixels, only viewport coordinates. Seems to work well to just drop the increment.
    table.insert(out, ('<text fill="black" x="%d" y="%d">%s</text>\n'):format(p.x, p.y+Drawing_text_baseline_height, p.name))
  end
end

function basename(s)
  return string.gsub(s, "(.*/)(.*)", "%2")
end