#import "@preview/touying:0.6.1": *

#let _tblock(self: none, title: none, it) = {
  grid(
    columns: 1,
    row-gutter: 0pt,
    block(
      fill: self.colors.primary-dark,
      width: 100%,
      radius: (top: 6pt),
      inset: (top: 0.4em, bottom: 0.3em, left: 0.5em, right: 0.5em),
      text(fill: self.colors.neutral-lightest, weight: "bold", title),
    ),
    rect(
      fill: gradient.linear(self.colors.primary-dark, self.colors.primary.lighten(90%), angle: 90deg),
      width: 100%,
      height: 4pt,
    ),
    block(
      fill: self.colors.primary.lighten(90%),
      width: 100%,
      radius: (bottom: 6pt),
      inset: (top: 0.4em, bottom: 0.5em, left: 0.5em, right: 0.5em),
      it,
    ),
  )
}

#let tblock(title: none, it) = touying-fn-wrapper(_tblock.with(title: title, it))

#let slide(
  title: auto,
  header: auto,
  footer: auto,
  align: auto,
  config: (:),
  repeat: auto,
  setting: body => body,
  composer: auto,
  ..bodies,
) = touying-slide-wrapper(self => {
  if align != auto {
    self.store.align = align
  }
  if title != auto {
    self.store.title = title
  }
  if header != auto {
    self.store.header = header
  }
  if footer != auto {
    self.store.footer = footer
  }
  let new-setting = body => {
    show: std.align.with(self.store.align)
    show: setting
    body
  }
  touying-slide(self: self, config: config, repeat: repeat, setting: new-setting, composer: composer, ..bodies)
})

#let title-slide(config: (:), ..args) = touying-slide-wrapper(self => {
  self = utils.merge-dicts(self, config)
  self.store.title = none
  let info = self.info + args.named()
  info.authors = {
    let authors = if "authors" in info {
      info.authors
    } else {
      info.author
    }
    if type(authors) == array {
      authors
    } else {
      (authors,)
    }
  }
  let body = {
    show: std.align.with(center + horizon)
    block(fill: self.colors.primary, inset: 1.5em, radius: 0.5em, breakable: false, {
      text(size: 1.2em, fill: self.colors.neutral-lightest, weight: "bold", info.title)
      if info.subtitle != none {
        parbreak()
        text(size: 1.0em, fill: self.colors.neutral-lightest, weight: "bold", info.subtitle)
      }
    })
    // authors
    grid(
      columns: (1fr,) * calc.min(info.authors.len(), 3),
      column-gutter: 1em,
      row-gutter: 1em,
      ..info.authors.map(author => text(fill: black, author)),
    )
    v(0.5em)
    // institution
    if info.institution != none {
      parbreak()
      text(size: 0.8em, info.institution)
    }
    // date
    if info.date != none {
      parbreak()
      text(size: 1.0em, utils.display-info-date(self))
    }
  }
  touying-slide(self: self, body)
})

#let outline-slide(
  config: (:),
  title: utils.i18n-outline-title,
  numbered: true,
  level: none,
  ..args,
) = touying-slide-wrapper(self => {
  self.store.title = "Indice"
  touying-slide(self: self, config: config, std.align(
    self.store.align,
    components.adaptive-columns({
      text(fill: self.colors.primary, weight: 600, components.custom-progressive-outline(
        level: level,
        alpha: self.store.alpha,
        indent: (0em, 1em),
        vspace: (.4em,),
        numbered: (numbered,),
        depth: 1,
        ..args.named(),
      ))
    })
      + args.pos().sum(default: none),
  ))
})

#let new-section-slide(
  config: (:),
  title: utils.i18n-outline-title,
  level: 1,
  numbered: true,
  ..args,
  body,
) = outline-slide(config: config, title: title, level: level, numbered: numbered, ..args, body)

#let focus-slide(config: (:), align: horizon + center, body) = touying-slide-wrapper(self => {
  self = utils.merge-dicts(self, config-common(freeze-slide-counter: true), config-page(
    fill: self.colors.primary,
    margin: 2em,
    header: none,
    footer: none,
  ))
  set text(fill: self.colors.neutral-lightest, weight: "bold", size: 1.5em)
  touying-slide(self: self, config: config, std.align(align, body))
})

#let ending-slide(config: (:), title: none, body) = touying-slide-wrapper(self => {
  let content = {
    set std.align(center + horizon)
    if title != none {
      block(fill: self.colors.tertiary, inset: (top: 0.7em, bottom: 0.7em, left: 3em, right: 3em), radius: 0.5em, text(
        size: 1.5em,
        fill: self.colors.neutral-lightest,
        title,
      ))
    }
    body
  }
  touying-slide(self: self, config: config, content)
})

#let dm-unipi-theme(
  aspect-ratio: "16-9",
  align: horizon,
  alpha: 20%,
  title: self => utils.display-current-heading(depth: self.slide-level),
  header-right: self => self.info.logo,
  progress-bar: true,
  footer-columns: (25%, 1fr, 5em),
  footer-a: self => self.info.author,
  footer-c: self => if self.info.short-title == auto {
    self.info.title
  } else {
    self.info.short-title
  },
  footer-d: context utils.slide-counter.display() + " / " + utils.last-slide-number,
  ..args,
  body,
) = {
  let header(self) = {
    set std.align(top)
    grid(
      rows: (auto, auto),
      utils.call-or-display(self, self.store.navigation),
      utils.call-or-display(self, self.store.header),
    )
  }
  let footer(self) = {
    set text(size: .5em)
    set std.align(center + bottom)
    grid(
      rows: (auto, auto),
      utils.call-or-display(self, self.store.footer),
      if self.store.progress-bar {
        utils.call-or-display(self, components.progress-bar(
          height: 2pt,
          self.colors.primary,
          self.colors.neutral-lightest,
        ))
      },
    )
  }

  show: touying-slides.with(
    config-page(
      paper: "presentation-" + aspect-ratio,
      header: header,
      footer: footer,
      header-ascent: 0em,
      footer-descent: 0em,
      margin: (top: 3.5em, bottom: 2.5em, x: 2.5em),
    ),
    config-common(slide-fn: slide, new-section-slide-fn: new-section-slide),
    config-methods(
      init: (self: none, body) => {
        set text(size: 18pt, font: "Open Sans")
        set par(leading: 0.75em)
        set list(marker: {
          place(top + left, dy: 0.2em, circle(fill: self.colors.primary, radius: 3pt))
          h(0.25em)
        })
        show figure.caption: set text(size: 0.6em)
        show footnote.entry: set text(size: 0.6em)
        show heading: set text(fill: self.colors.primary)
        show link: it => if type(it.dest) == str {
          set text(fill: self.colors.primary)
          it
        } else {
          it
        }
        show figure.where(kind: table): set figure.caption(position: top)

        body
      },
      alert: utils.alert-with-primary-color,
      tblock: _tblock,
    ),
    config-colors(
      primary: rgb("#003c71"),
      primary-dark: rgb("#005baa"),
      secondary: rgb("#ffffff"),
      neutral-lightest: rgb("#ffffff"),
      neutral-darkest: rgb("#001c35"),
    ),
    config-store(
      align: align,
      alpha: alpha,
      title: title,
      header-right: header-right,
      progress-bar: progress-bar,
      footer-columns: footer-columns,
      footer-a: footer-a,
      footer-c: footer-c,
      footer-d: footer-d,
      navigation: self => components.simple-navigation(
        self: self,
        primary: white,
        secondary: gray,
        background: self.colors.neutral-darkest,
        logo: utils.call-or-display(self, self.store.header-right),
      ),
      header: self => if self.store.title != none {
        block(width: 100%, height: 2em, fill: self.colors.primary, place(
          left + horizon,
          text(fill: self.colors.neutral-lightest, weight: 600, size: 1.2em, utils.call-or-display(
            self,
            self.store.title,
          )),
          dx: 1.5em,
        ))
      },
      footer: self => {
        let cell(fill: none, it) = rect(
          width: 100%,
          height: 100%,
          inset: 1mm,
          outset: 0mm,
          fill: fill,
          stroke: none,
          std.align(horizon, text(fill: self.colors.neutral-lightest, it)),
        )
        grid(
          columns: self.store.footer-columns,
          rows: (1.5em, auto),
          cell(fill: self.colors.neutral-darkest, utils.call-or-display(self, self.store.footer-a)),
          cell(fill: self.colors.primary, utils.call-or-display(self, self.store.footer-c)),
          cell(fill: self.colors.primary, utils.call-or-display(self, self.store.footer-d)),
        )
      },
    ),
    ..args,
  )

  body
}
