// set some styles
#let style(it) = {
  show heading: set text(font: "New Computer Modern")
  show link: underline
  it
}

// transform md-similes to actual symbols
#let smartypants(it) = {
  // smartypants and latex compatibility
  show "--": [#sym.dash.en]
  show "---": [#sym.dash.em]
  show "\&": [#sym.amp]
  it
}

// Choose the compiled language through cli by doing
//
// $ typst compile --input lang=de cv.typ
//
#let lang = {
  if "lang" in sys.inputs and sys.inputs.lang == "de" {
    "de"
  } else {
    "en"
  }
}

#let _columns_3(left_body, center_body, right_body) = {
  block[
    #box(width: 1fr)[
      #align(left)[#left_body]
    ]
    #box(width: 1fr)[
      #align(center)[#center_body]
    ]
    #box(width: 1fr)[
      #align(right)[#right_body]
    ]
  ]
}

#let header(about, columns: (1.5fr, 1fr, 1fr)) = {
  [= #about.fullname]
  let contact_fields = (
    for c in about.contact {
      if "link" in c {
        ([#c.icon ~ #link(c.link)[#c.text]],)
      } else {
        ([#c.icon ~ #c.text],)
      }
    }
  )
  grid(
    columns: columns,
    gutter: 5pt,
    ..contact_fields
  )
}

#let subdued(body) = {
  block(inset: 5%, width: 85%, text(fill: luma(150), body))
}

#let entry(item: ()) = {
  if "title" in item {
    [*#item.title.at(lang)*]
  }
  if "place" in item {
    if "title" in item {
      [, ]
    }
    [_#item.place.at(lang)_]
  }
  [#h(1fr)]
  if "date" in item {
    [ _#item.date.at(lang)_ \ ]
  }
  if "bullets" in item {
    for bullet in item.bullets {
      [- #bullet.at(lang)]
    }
  }
  if "publication" in item {
    subdued[#item.publication.at(lang) \ ]
  }
  if "abstract" in item {
    subdued[#item.abstract.at(lang) \ ]
  }
}

#let horizon_line() = {
  v(-3pt)
  line(length: 100%)
  v(-5pt)
}

#let section_header(title) = {
  [== #title]
  horizon_line()
};

#let section(title: "Section", entries: (), body) = {
  section_header(title)
  if body == none or body == [] {
    for e in entries {
      entry(item: e)
    }
  } else {
    body
  }
};

// Slightly re-styled entry with PLACE first and TITLE second
#let education_entry(item: ()) = {
  assert(
    "place" in item and "title" in item and "date" in item,
    message: "Education items require place, program and date.",
  )
  [*#item.place.at(lang)*, #item.title.at(lang) #h(1fr)]
  [ _#item.date.at(lang)_ \ ]
}

// Restyled entry with PLACE not emphasized like usual, and no date but an abstract
#let thesis_entry(item: ()) = {
  assert("title" in item and "place" in item, message: "Thesis items require type and title.")
  [*#item.title.at(lang)* #item.place.at(lang) #h(1fr)]
  [#par(item.abstract.at(lang))]
}

// skill-specific entry, changing its style for sidebar
#let skill_item(item: (), is_sidebar: false) = {
  let side_list(body) = if is_sidebar { list(body) } else { par(body) }
  for skill in item {
    side_list({
      [*#skill.name.at(lang)*]
      if is_sidebar [\ ] else [ (]
      for (i, v) in skill.items.enumerate() {
        [#v.at(lang)]
        if i < skill.items.len() - 1 {
          [, ]
        }
      }
      if not is_sidebar [)]
    })
  }
}