#import "utils.typ"

// set rules
#let setrules(uservars, doc) = {
  set text(font: uservars.bodyfont, size: uservars.fontsize, hyphenate: false)

  set list(spacing: uservars.linespacing)

  set par(leading: uservars.linespacing, justify: true)

  doc
}

// show rules
#let showrules(uservars, doc) = {
  // uppercase section headings
  show heading.where(level: 2): it => block(width: 100%)[
    #set align(left)
    #set text(font: uservars.headingfont, size: 1em, weight: "bold")
    #if (uservars.at("headingsmallcaps", default: false)) {
      smallcaps(it.body)
    } else {
      it.body
    }
    #v(-0.75em) #line(length: 100%, stroke: 1pt + black) // draw a line
  ]

  // name title
  show heading.where(level: 1): it => block(width: 100%)[
    #set text(font: uservars.headingfont, size: 2em, weight: "bold")
    #if (uservars.at("headingsmallcaps", default: false)) {
      smallcaps(it.body)
    } else {
      // upper(it.body)
      it.body
    }
    #v(2pt)
  ]

  doc
}

// set page layout
#let cvinit(doc) = {
  doc = setrules(doc)
  doc = showrules(doc)

  doc
}

// address
#let addresstext(lang, info, uservars) = {
  if uservars.showAddress {
    block(
      width: 100%,
    )[
      #info.personal.location.city, #info.personal.location.region, #info.personal.location.country
      #v(-4pt)
    ]
  } else { none }
}

#let fa(body) = {
  set text(font: "FontAwesome")
  [#body]
}

#let contacttext(lang, info, uservars) = block(
  width: 100%,
)[
  #let profiles = (
    box(link("mailto:" + info.personal.email)[#fa(" ") #info.personal.email]),
    if uservars.showNumber { box(link("tel:" + info.personal.phone)[#fa("") #info.personal.phone]) } else { none },
    if info.personal.at("url", default: none) != none {
      box(
        link(info.personal.url)[#fa(" ") #info.personal.url.split("//").at(1)],
      )
    },
  ).filter(it => it != none) // filter out none elements from the profile array

  #if info.personal.profiles.len() > 0 {
    for profile in info.personal.profiles {
      profiles.push(box(link(profile.url)[#profile.username]))
    }
  }

  #set text(font: uservars.bodyfont, weight: "light", size: uservars.fontsize * 1)
  #pad(x: 0em)[
    #profiles.join([#sym.space.en|#sym.space.en])
  ]
]

#let cvheading(lang, info, uservars) = {
  align(center)[
    = #info.personal.name
    #addresstext(lang, info, uservars)
    #contacttext(lang, info, uservars)
  ]
}

#let cvwork(lang, info, isbreakable: true) = {
  if info.experience != none {
    block[
      == #info.experience.title
      #for w in info.experience.content {
        block(width: 100%, breakable: isbreakable)[
          #if w.url != none [
            *#link(w.url)[#w.with]* #h(1fr) *#w.where* \
          ] else [
            *#w.with* #h(1fr) *#w.where* \
          ]
        ]
        // create a block layout for each work entry
        let index = 0
        for p in w.what {
          if index != 0 { v(0.6em) }
          block(
            width: 100%,
            breakable: isbreakable,
            above: 0.6em,
          )[
            // parse ISO date strings into datetime objects
            #let start = utils.strpdate(lang, p.startDate)
            #let end = utils.strpdate(lang, p.endDate)
            // line 2: position and date range
            #text(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#p.what #h(1fr)
              #start #sym.dash.en #end] \
            // highlights or description
            #for hi in p.why [
              - #text(weight: "light")[#eval(hi, mode: "markup")]
            ]
          ]
          index = index + 1
        }
      }
    ]
  }
}

#let cveducation(lang, info, isbreakable: true) = {
  let education = info.education
  if education != none {
    block[
      == #education.title
      #for edu in education.content {
        let start = utils.strpdate(lang, edu.startDate)
        let end = utils.strpdate(lang, edu.endDate)
        let eduurl = edu.at("url", default: none)

        // create a block layout for each education entry
        block(
          width: 100%,
          breakable: isbreakable,
        )[
          // line 1: institution and location
          #if eduurl != none {
            text(weight: "extrabold")[
              #link(eduurl)[#edu.with] #h(1fr) #edu.where \
            ]
          } else {
            text(weight: "extrabold")[
              #edu.with #h(1fr) #edu.where \
            ]
          }
          // line 2: degree and date
          #text(weight: "semibold", size: 9.0pt, fill: luma(30.6%))[#edu.what #h(1fr)
            #start #sym.dash.en #end] \

          #for hi in edu.why [
            - #text(weight: "light")[#eval(hi, mode: "markup")]
          ]
        ]
      }
    ]
  }
}

#let cvaffiliations(lang, info, isbreakable: true) = {
  if info.affiliations != none {
    block[
      == Leadership & Activities
      #for org in info.affiliations {
        // parse ISO date strings into datetime objects
        let start = utils.strpdate(lang, org.startDate)
        let end = utils.strpdate(lang, org.endDate)

        // create a block layout for each affiliation entry
        block(width: 100%, breakable: isbreakable)[
          // line 1: organization and location
          #if org.url != none [
            *#link(org.url)[#org.with]* #h(1fr) *#org.where* \
          ] else [
            *#org.with* #h(1fr) *#org.where* \
          ]
          // line 2: position and date
          #text(style: "italic")[#org.position] #h(1fr)
          #start #sym.dash.en #end \
          // highlights or description
          #if org.highlights != none {
            for hi in org.highlights [
              - #eval(hi, mode: "markup")
            ]
          } else {}
        ]
      }
    ]
  }
}

#let cvprojects(lang, info, isbreakable: true) = {
  if info.projects != none {
    block[
      == Projects
      #for project in info.projects {
        // parse ISO date strings into datetime objects
        let start = utils.strpdate(lang, project.startDate)
        let end = utils.strpdate(lang, project.endDate)
        // create a block layout for each project entry
        block(
          width: 100%,
          breakable: isbreakable,
        )[
          // line 1: project name
          #if project.url != none [
            *#link(project.url)[#project.name]* \
          ] else [
            *#project.name* \
          ]
          // line 2: organization and date
          #text(style: "italic")[#project.affiliation] #h(1fr) #start #sym.dash.en #end \
          // summary or description
          #for hi in project.highlights [
            - #eval(hi, mode: "markup")
          ]
        ]
      }
    ]
  }
}

#let cvawards(lang, info, isbreakable: true) = {
  if info.awards != none {
    block[
      == Honors & Awards
      #for award in info.awards {
        // parse ISO date strings into datetime objects
        let date = utils.strpdate(lang, award.date)
        // create a block layout for each award entry
        block(width: 100%, breakable: isbreakable)[
          // line 1: award title and location
          #if award.url != none [
            *#link(award.url)[#award.title]* #h(1fr) *#award.location* \
          ] else [
            *#award.title* #h(1fr) *#award.location* \
          ]
          // line 2: issuer and date
          Issued by #text(style: "italic")[#award.issuer] #h(1fr) #date \
          // summary or description
          #if award.highlights != none {
            for hi in award.highlights [
              - #eval(hi, mode: "markup")
            ]
          } else {}
        ]
      }
    ]
  }
}

#let cvcertificates(lang, info, isbreakable: true) = {
  if info.certificates != none {
    block[
      == Licenses & Certifications

      #for cert in info.certificates {
        // parse ISO date strings into datetime objects
        let date = utils.strpdate(lang, cert.date)
        // create a block layout for each certificate entry
        block(width: 100%, breakable: isbreakable)[
          // line 1: certificate name
          #if cert.url != none [
            *#link(cert.url)[#cert.name]* \
          ] else [
            *#cert.name* \
          ]
          // line 2: issuer and date
          Issued by #text(style: "italic")[#cert.issuer] #h(1fr) #date \
        ]
      }
    ]
  }
}

#let cvpublications(lang, info, isbreakable: true) = {
  if info.publications != none {
    block[
      == Research & Publications
      #for pub in info.publications {
        // parse ISO date strings into datetime objects
        let date = utils.strpdate(lang, pub.releaseDate)
        // create a block layout for each publication entry
        block(width: 100%, breakable: isbreakable)[
          // line 1: publication title
          #if pub.url != none [
            *#link(pub.url)[#pub.name]* \
          ] else [
            *#pub.name* \
          ]
          // line 2: publisher and date
          Published on #text(style: "italic")[#pub.publisher] #h(1fr) #date \
        ]
      }
    ]
  }
}

#let cvlanguages(lang, info, isbreakable: true) = {
  block(breakable: isbreakable)[
    == #info.languages.title

    #for lang in info.languages.content {
      [- *#lang.title*#text(weight: "light")[: #lang.content]]
    }
  ]
}

#let cvskills(lang, info, isbreakable: true) = {
  block(
    breakable: isbreakable,
  )[
    == #info.skills.title

    #for skill in info.skills.content {
      let skillContent = skill.content.sorted(key: x => {
        if type(x) == dictionary {
          x.keys().first()
        } else { x }
      }).map(
        x => {
          if type(x) == dictionary {
            [#x.keys().first() (#text(style: "italic")[#x.values().first().sorted().join(", ")])]
          } else {
            [#x]
          }
        },
      ).join(", ")

      [- *#skill.title*#text(weight: "light")[: #skillContent]]
    }
  ]
}

#let cvreferences(info, isbreakable: true) = {
  if info.references != none {
    block[
      == References
      #for ref in info.references {
        block(width: 100%, breakable: isbreakable)[
          #if ref.url != none [
            - *#link(ref.url)[#ref.name]*: "#ref.reference"
          ] else [
            - *#ref.name*: "#ref.reference"
          ]
        ]
      }
    ]
  } else {}
}

#let endnote() = {
  place(bottom + right, block[
    #set text(size: 5pt, font: "Consolas", fill: silver)
    Félix Desmaretz #datetime.today().display("[year]-[month]-[day]")
  ])
}