#import "@preview/codly:0.2.1": *
#import "@preview/tablex:0.0.8": tablex, hlinex
#import "@preview/tablem:0.1.0": tablem
#import "@preview/outrageous:0.1.0"
#import "@preview/cuti:0.2.1": show-cn-fakebold


// reference: https://github.com/lucifer1004/pkuthss-typst/blob/main/template.typ
#let 字号 = (
  初号: 42pt,
  小初: 36pt,
  一号: 26pt,
  小一: 24pt,
  二号: 22pt,
  小二: 18pt,
  三号: 16pt,
  小三: 15pt,
  四号: 14pt,
  中四: 13pt,
  小四: 12pt,
  五号: 10.5pt,
  小五: 9pt,
  六号: 7.5pt,
  小六: 6.5pt,
  七号: 5.5pt,
  小七: 5pt,
)

#let 字体 = (
  仿宋: ("Times New Roman", "FangSong"),
  宋体: ("Times New Roman", "SimSun"),
  黑体: ("Times New Roman", "SimHei"),
  楷体: ("Times New Roman", "KaiTi"),
  代码: ("New Computer Modern Mono", "Times New Roman", "SimSun"),
  得意黑: ("Smiley Sans",),
)


// 封面设置
#let CoverInfo(
  ClassName: "",
  ReportName: "",
  Name: "",
  StudentID: "",
  School: "",
) = {
  
  set text(font: 字体.宋体)

  set page(numbering: none)

  set align(center)

  figure(
    image(
      "assets/Icons/banner_zh_sjtu.png",
      width: 75%,
      )
  )

  v(-2em)

  figure(
    image(
      "assets/Icons/banner_eng_sjtu.png",
      width: 75%,
      )
  )

  v(-1.5em)

  figure(
    image(
      "assets/Icons/badge_sjtu.png",
      width: 30%,
      )
  )

  v(2em)

  par(
    text(
      font: 字体.黑体,
      size: 字号.二号,
      weight: "bold",
      [#ClassName] + "\n",
    )
  )

  par(
    text(
      font: 字体.黑体,
      size: 字号.三号,
      weight: "bold",
      "实验报告 - " + [#ReportName],
    )
  )

  v(4em)

  let info-key(key) = {
    rect(
      width: 100%,
      stroke: none,
      text(
        font: 字体.黑体,
        size: 字号.四号,
        weight: "bold",
        strong(key)
      ),
    )
  }

  let table-stroke = 0.5pt
  let info-value(value) = {
    rect(
      width: 100%,
      stroke: (bottom: table-stroke + black),
      text(
        font: 字体.黑体,
        size: 字号.四号,
        bottom-edge: "descender",
        value,
      ),
    )
  }

  grid(
    columns: (80pt, 160pt),
    row-gutter: 1em,
    column-gutter: 3pt,
    info-key(text("姓") + h(2em) + text("名：")), info-value[#Name],
    info-key(text("学") + h(2em) + text("号：")), info-value[#StudentID],
    info-key(text("学") + h(2em) + text("院：")), info-value[#School],
  )

  v(8em)

  text(
    font: 字体.黑体,
    size: 字号.三号,
    weight: "bold",
    datetime.today().display("[year]年[month]月[day]日"),
  )

  pagebreak(weak: true)

}


// 目录设置
#let ChineseOutline() = {
  set text(font: 字体.宋体, size: 字号.小四)
  show: show-cn-fakebold

  set align(center)

  set page(numbering: "I")
  counter(page).update(1)

  set par(
    justify: true,
    first-line-indent: 2em,
  )

  // 一级目录字体、间距设置
  show outline.entry.where(
    level: 1
  ): it => {
    set text(size: 字号.中四)
    v(2pt)
    strong(it)
  }

  // outrageous 目录设置
  show outline.entry: outrageous.show-entry.with(
    ..outrageous.presets.typst,
    fill: (none, auto),
  )

  outline(
    title: text("目录"), 
    indent: 1em,
  )

  pagebreak(weak: true)

}

// 报告模板
#let ReportTemplate(
  ClassName: "",
  ReportName: "",
  Name: "",
  StudentID: "",
  School: "",
  body
) = {
  
  /*  ###################   封面设置   ######################  */
  CoverInfo(
    ClassName: ClassName,
    ReportName: ReportName,
    Name: Name,
    StudentID: StudentID,
    School: School,
  )


  /*  ###################   目录设置   ######################  */
  ChineseOutline()


  /*  ###################   正文设置   ######################  */

  // 字体设置
  show: show-cn-fakebold
  set text(font: 字体.宋体, size: 字号.小四)

  // 数学公式标号格式: (章节.数字)
  set math.equation(numbering: num =>
  "(" + str(counter(heading).get().first()) + "." + str(num) + ")")

  // 标题编号
  set heading(numbering: "1.1.1.1.")

  set page(
    // 页眉设置
    header: context {
      set text(font: 字体.宋体, size: 字号.小五)

      set par(leading: 12pt)
      show par: set block(spacing: 0pt)

      v(-6pt)
      line(length: 100%, stroke: 2.2416pt)
      v(-8pt)
      line(length: 100%, stroke: 0.7472pt)
      v(12pt)
    },

    // 页脚设置
    footer: context {
      set align(center)
      set text(size: 字号.小五)
      counter(page).display()
    }
  )

  set par(
    first-line-indent: 2em,
    justify: true,
  )

  // 解决标题后首段无法正确缩进问题
  // 在标题后面添加空白段 使得首段不再是首段
  show heading: it => {
    it
    par(leading: 1.5em)[#text(size:0.0em)[#h(0.0em)]]
  }

  counter(page).update(1)

  body
}


// 编程语言图标
#let icon(codepoint) = {
  box(
    height: 0.8em,
    baseline: 0.05em,
    image(codepoint)
  )
  h(0.1em)
}

// 三线表
#let three-line-table = tablem.with(
  render: (columns: auto, ..args) => {
    tablex(
      columns: columns,
      auto-lines: false,
      align: center + horizon,
      hlinex(y: 0),
      hlinex(y: 1),
      ..args,
      hlinex(),
    )
  }
)
