local ls = require("luasnip")
local s = ls.snippet
local sn = ls.snippet_node
local isn = ls.indent_snippet_node
local t = ls.text_node
local i = ls.insert_node
local f = ls.function_node
local c = ls.choice_node
local d = ls.dynamic_node
local r = ls.restore_node
local events = require("luasnip.util.events")
local ai = require("luasnip.nodes.absolute_indexer")
local extras = require("luasnip.extras")
local l = extras.lambda
local rep = extras.rep
local p = extras.partial
local m = extras.match
local n = extras.nonempty
local dl = extras.dynamic_lambda
local fmt = require("luasnip.extras.fmt").fmt
local fmta = require("luasnip.extras.fmt").fmta
local conds = require("luasnip.extras.expand_conditions")
local postfix = require("luasnip.extras.postfix").postfix
local types = require("luasnip.util.types")
local parse = require("luasnip.util.parser").parse_snippet
local ms = ls.multi_snippet
local k = require("luasnip.nodes.key_indexer").new_key
local matches = require("luasnip.extras.postfix").matches

local case_template = [[
case {expression} {{
  {pattern1} -> {result1}
  {pattern2} -> {result2}{final}
}}
]]

local dot_case = postfix({ filetype = "gleam", trig = ".case", match_pattern = matches.line }, {
  d(1, function(_, parent)
    return sn(
      1,
      fmt(case_template, {
        expression = t(parent.env.POSTFIX_MATCH),
        pattern1 = i(1, "pattern"),
        result1 = i(2, "todo"),
        pattern2 = i(3, "_"),
        result2 = i(4, "todo"),
        final = i(0),
      })
    )
  end),
})

local case = s(
  { filetype = "gleam", trig = "case" },
  fmt(case_template, {
    expression = i(1),
    pattern1 = i(2),
    result1 = i(3, "todo"),
    pattern2 = i(4, "_"),
    result2 = i(5, "todo"),
    final = i(0),
  })
)

local fn_template = [[
fn {name}({args}) -> {rtype} {{
  {body}
}}
]]

local fn = s(
  { filetype = "gleam", trig = "fn" },
  fmt(fn_template, {
    name = i(1),
    args = i(2),
    rtype = i(3),
    body = i(0),
  })
)

local pfn = s(
  { filetype = "gleam", trig = "pfn" },
  fmt("pub " .. fn_template, {
    name = i(1),
    args = i(2),
    rtype = i(3),
    body = i(0),
  })
)

local type_template = [[
type {name} {{
  {body}
}}
]]

local type = s(
  { filetype = "gleam", trig = "type" },
  fmt(type_template, {
    name = i(1),
    body = i(0),
  })
)

local ptype = s(
  { filetype = "gleam", trig = "ptype" },
  fmt("pub " .. type_template, {
    name = i(1),
    body = i(0),
  })
)

return {
  case,
  dot_case,
  fn,
  pfn,
  type,
  ptype,
}