/***************************************************************
 * A polylux theme by martino barbieri (https://mbarbieri.it)  *
 * https://gitlab.com/martino.barbieri/polylux-sns-template/   *
 * Patched for the PhD defence of Jean-Marie Mineau            *
 * LICENSE: MIT-0                                              *
 ***************************************************************/

#import "@preview/polylux:0.4.0" as pl: *

/* PER TEMPLATE SNS */
// Background and decorations
#let sns-polylux-template_sns-colormap = (
rgb("#00728D"),
rgb("#183F56"),
rgb("#4D4E4F"),
rgb("#AB3502"),
rgb("#E69426"),
rgb("#9CD7F3"),
)

/* PER TEMPLATE UNIPI */
#let sns-polylux-template_unipi-colormap = (
cmyk(100%,57%,0%,9%),
cmyk(100%,57%,0%,38%),
rgb("#444444"),
rgb("#AB3502"),
rgb("#E69426"),
cmyk(25%,7%,0%,0%),
)

#let sns-polylux-template_colormap              = state("colormap",    none)

// Text and Fonts
#let sns-polylux-template_text-font             = state("txt-font",    none)
#let sns-polylux-template_title-font            = state("title-font",  none)
#let sns-polylux-template_background-color      = state("bkg_color1",  none)
#let sns-polylux-template_main-text-color       = state("txt_color1",  none)
#let sns-polylux-template_second-text-color     = state("txt_color2",  none)
#let sns-polylux-template_title-text-color      = state("title_color", none)
#let sns-polylux-template_size                  = state("size",        none)
#let sns-polylux-template_title-size            = state("title-size",  none)

// Data
#let sns-polylux-template_title                 = state("title",       none)
#let sns-polylux-template_short-title           = state("short-title", none)
#let sns-polylux-template_subtitle              = state("subtitle",    none)
#let sns-polylux-template_event                 = state("event",       none)
#let sns-polylux-template_short-event           = state("short-event", none)
#let sns-polylux-template_authors               = state("authors",     none)

#let sns-polylux-template_logo-1                = state("logo-1",      none)
#let sns-polylux-template_logo-2                = state("logo-2",      none)

#let sns-polylux-template_date                  = state("date",      none)

#let sns-polylux-template_section-pages         = state("section-pages", ("plop": 0))
#let sns-polylux-template_slide-pages           = state("slide-pages", 0)

// Init
#let sns-polylux-template(
  // General parameters
  aspect-ratio : "16-9",

  txt-font     : ("Roboto", "Fira Sans", "DejaVu Sans"),
  title-font   : ("Raleway", "PT Sans", "DejaVu Sans"),
  txt-color1   : black,
  txt-color2   : white,
  title-color  : rgb("#444444"),
  size         : 20pt,
  title-size   : 64pt,
  bkgnd-color  : white,

  colormap     : sns-polylux-template_sns-colormap,

  // Data
  title        : none,
  subtitle     : none,
  short-title  : none,
  event        : none,
  short-event  : none,
  logo-2       : none,
  logo-1       : none,
  authors      : none,
  date         : none, 
  // Stuff
  body
) = {
  sns-polylux-template_text-font.update(txt-font)
  sns-polylux-template_title-font.update(title-font)
  sns-polylux-template_background-color.update(bkgnd-color)
  sns-polylux-template_main-text-color.update(txt-color1)
  sns-polylux-template_second-text-color.update(txt-color2)
  sns-polylux-template_title-text-color.update(title-color)
  sns-polylux-template_size.update(size)
  sns-polylux-template_title-size.update(title-size)

  sns-polylux-template_colormap.update(colormap)

  set page(
    paper          : "presentation-" + aspect-ratio,
    fill           : bkgnd-color,
    margin         : 0pt,
    header         : none,
    footer         : none,
    header-ascent  : 0pt,
    footer-descent : 0pt,
  )
  set text(
    fill : txt-color1,
    size : size,
    font : txt-font,
  )
  sns-polylux-template_title.update(title)
  sns-polylux-template_subtitle.update(subtitle)
  if short-title != none { sns-polylux-template_short-title.update(short-title) }
    else { sns-polylux-template_short-title.update(title) }
  sns-polylux-template_event.update(event)
  if short-event != none { sns-polylux-template_short-event.update(short-event) }
    else { sns-polylux-template_short-event.update(event) }
  sns-polylux-template_logo-2.update(logo-2)
  sns-polylux-template_logo-1.update(logo-1)
  sns-polylux-template_authors.update(authors)
  sns-polylux-template_date.update(date)

  body

  context {
    //let section-pages = sns-polylux-template_section-pages.final()
    if not "END" in sns-polylux-template_section-pages.at(here()).keys() {
      let page_num = counter("logical-slide").at(here())
      sns-polylux-template_section-pages.update(secpages => {
        secpages.insert("END", page_num)
        secpages
      })
    }
  }
}

#let register-section(title, no_dedicated_slide: false) = context {
  // YUCKKKKK, but polylux don't allows access to integers soooooo
  let page_num = counter("logical-slide").at(here()) //sns-polylux-template_slide-pages.at(here())
  if no_dedicated_slide {
    page_num.at(0) += 1
  }
  sns-polylux-template_section-pages.update(secpages => {
    secpages.insert(repr(title), page_num)
    secpages
  })
  pl.toolbox.register-section(title)
}

#let progress-bar() = pl.toolbox.progress-ratio( ratio => {
  let colormap = sns-polylux-template_colormap.at(here())
  let height = 3pt
  stack(dir: ltr, 
    rect(width: ratio * 100%, height: height, fill: colormap.at(5)),
    rect(width: (1-ratio) * 100%, height: height, fill: colormap.at(0)),
  )
})

// Slides
#let title-slide(
  body            : none,
  logo            : none,
  background      : [],
  foreground      : [],
) = context( {
  let content = align(top + center, context( {
    let title       = sns-polylux-template_title.at(here())
    let subtitle    = sns-polylux-template_subtitle.at(here())
    let event       = sns-polylux-template_event.at(here())
    let authors     = sns-polylux-template_authors.at(here())
    let title-size  = sns-polylux-template_title-size.at(here())
    let logo        = {
      if logo == none   { sns-polylux-template_logo-1.at(here()) }
      else              { logo }
    }
    let date        = sns-polylux-template_date.at(here())

    // Background
    place(
      bottom + right,
      polygon(
        fill   : sns-polylux-template_colormap.at(here()).at(2),
        stroke : none,
        (0%, 42%),(100%, 42%),(100%, 0%),
      ),
    )
    place(
      bottom + right,
      polygon(
        fill   : sns-polylux-template_colormap.at(here()).at(1),
        stroke : none,
        (0%, 29%),(0%, 37%),(100%, 37%),(100%, 0%),
      ),
    )
    place(
      bottom + right,
      polygon(
        fill   : sns-polylux-template_colormap.at(here()).at(0),
        stroke : none,
        (0%, 20%),(0%, 30%),(100%, 30%),(100%, 0%),
      ),
    )
    place(
      top + left,
      polygon(
        fill   : sns-polylux-template_colormap.at(here()).at(2),
        stroke : none,
        (0%, 0%),(0%, 16%),(75%, 0%),
      ),
    )
    place(
      top + left,
      polygon(
        fill   : sns-polylux-template_colormap.at(here()).at(0),
        stroke : none,
        (0%, 0%),(0%, 15%),(75%, 0%),
      ),
    )
    place(
      bottom + center,
      dy: -1cm,
      text(fill: sns-polylux-template_background-color.at(here()), size: 22pt, event)
    )
    if logo != none {
      place(
        bottom + right,
        dx: -0.5cm,
        dy: -0.3cm,
        scale(page.height/measure(logo).height*22%, reflow: true, logo)
      )
    }

    // Contents
    set align(center+top)
    v(17%)
    text(
      font : sns-polylux-template_title-font.at(here()),
      size : title-size,
      fill: sns-polylux-template_title-text-color.at(here()),
      weight: "bold",
      title
    )
    linebreak()
    v(0em)
    text(
      font : sns-polylux-template_title-font.at(here()),
      size : 22pt,
      fill: sns-polylux-template_title-text-color.at(here()),
      subtitle
    )
    //v(-0.9em)
    line(length: 90%, stroke: (paint: sns-polylux-template_colormap.at(here()).at(5), thickness: 4pt))
    v(1em)
    set text(
      size: 24pt,
      top-edge: 0pt,
      bottom-edge: 0pt,
      fill: sns-polylux-template_main-text-color.at(here())
    )
    {
      set align(left)
      for i in range(authors.len()) {
        h(1em)
        authors.at(i)
        v(0.5em)
        //move(dx: 2% * ( i - ( authors.len() - 1 ) / 2 ), authors.at(i))
      }
      if date != none {
        v(1em)
        h(1em)
        date.display()
      }
    }
    body
  } ))

  set page(background: background, foreground: foreground)
  pl.slide({ content })

  counter("logical-slide").update( n => n - 1 )
} )

#let sections() = context {
  let section-pages = sns-polylux-template_section-pages.final()
  let pnum = counter("logical-slide").at(here()).first() + 1
  pl.toolbox.all-sections((sections, current) => {
    let beg-end-section = (:)
    let prev-sec = none
    for section in sections {
      let s = repr(section.at("body"))
      if prev-sec != none {
        beg-end-section.insert(prev-sec, (section-pages.at(prev-sec).first(), section-pages.at(s).first()))
      }
      prev-sec = s
    }
    if prev-sec != none {
      beg-end-section.insert(prev-sec, (section-pages.at(prev-sec).first(), section-pages.at("END").first() + 1))
    }

    let section_names = ()
    let section_pages = ()
    for s in sections {
        let pages = ()
        let (pmin, pmax) = beg-end-section.at(repr(s.at("body")))

        let p_i = pmin 
        while p_i < pmax and p_i < pnum {
          // In section, before current page
          pages.push(sym.circle.filled)
          p_i += 1
        }
        if p_i == pnum and p_i != pmax {
          // In section, current page
          pages.push(sym.ast.circle)
          p_i += 1
        }
        while p_i < pmax {
          // In section, after current page
          pages.push(sym.circle.dotted)
          p_i += 1
        }

        //section_names.push(scale(50%, reflow: true, [#pnum #s (#pmin, #pmax)]))
        if s == current { 
          section_names.push(strong(s))
          section_pages.push(strong(pages.join([])))
        } else {
          section_names.push(s)
          section_pages.push(pages.join([]))
        }
    }
    grid(
      columns: (auto,)*section_names.len(),
      column-gutter: 1fr,
      row-gutter: 12pt,
      ..section_names, ..section_pages,
    )
  })
}

/*
#let small-sections(show-sec-name: true) = context( {
  set text(bottom-edge: "descender")
  if show-sec-name {pl.toolbox.current-section;" "}

  pl.toolbox.all-sections(
    (sections, current) => {
      let over_current = false
      for i in sections {
        if current == i {$ast.circle$; over_current = true}
        else if (over_current or current not in sections) {
          $circle.dotted$
        } else {$circle.filled$}
      }
    }
  )
} )

#let big-sections = context( {
  set align(horizon + right)
  grid(
  box(height: 40%, inset: 0.8cm)[#small-sections(show-sec-name: false)],
  box(height: 60%, inset: 0.8cm)[
    #pl.toolbox.current-section
  ])
} )
*/

#let slide(
  title           : none,
  subtitle        : none,
  new-sec         : false,
  page-number     : true,
  hide-section    : false,
  hide-title      : false,
  background      : [],
  foreground      : [],
  body
) = context( {
  let sections_height = 1.5cm
  let progress_bar_height = 3pt
  let title_bar_height = 2cm

  // HEADER
  let header = align(top, context( {
    let logo = sns-polylux-template_logo-2.at(here())

    // If new-sec is false, do nothing
    // If new-sec is true, new section's name is the slide title
    // Else the new-sec name is new-sec
    if type(new-sec)==bool {
      if new-sec {
        register-section(title, no_dedicated_slide: true)
      }
    } else {
      register-section(new-sec)
    }

    place(top + left, {
      let columns = if logo != none { (auto, 1fr,) } else { (1fr,) };
      grid(
        columns: columns,
        gutter: 0pt,

        if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } else { [] },
        rect(
          width: 100%, height: sections_height,
          inset: 0.8cm, outset: 0pt,
          fill: sns-polylux-template_colormap.at(here()).at(1),

          align(horizon + center,text(fill: sns-polylux-template_second-text-color.at(here()), {
            v(-1em)
            if hide-section { hide(sections()) } else { sections() }
          }))
        ),
        grid.cell(colspan: columns.len(), progress-bar()),
        if title != none and not hide-title {
          rect(
            width: 100%, height: title_bar_height,
            inset: 0.8cm, outset: 0pt,
            fill: sns-polylux-template_colormap.at(here()).at(0),

            align(horizon + center, {
              text(
                fill: sns-polylux-template_second-text-color.at(here()),
                font: sns-polylux-template_title-font.at(here()),
                size: 32pt,
                weight: "bold",
                title
              )
              if subtitle != none {
                smallcaps(text(
                  fill: sns-polylux-template_second-text-color.at(here()),
                  font: sns-polylux-template_title-font.at(here()),
                  size: 24pt,
                  " — " + subtitle
                ))
              }
            })
          )
        } else { [] }
      ) 
    }) // closes `place(top+left, {`
  } )) // closes `let header = ...`

  // FOOTER
  let footer = align(top + center, context( {
    let short-title = sns-polylux-template_short-title.at(here())
    let short-event = sns-polylux-template_short-event.at(here())

    place(top + center, line(length: 100%-2cm, stroke: (paint: sns-polylux-template_colormap.at(here()).at(1), thickness: 2pt)))

    set text(bottom-edge: "descender")

    block(
      height: 100%,
      width: 100%,
      inset: (x: 0.8cm),
      align(horizon,text(fill: sns-polylux-template_colormap.at(here()).at(2), size: 16pt,
      grid(
        gutter: 0.8cm,
        columns: (0.7fr, 1fr, 0.7fr),
        align(left, short-title),
        align(center, smallcaps(short-event)),
        align(right, if page-number [#toolbox.slide-number/#toolbox.last-slide-number]),
      ))
    ))
  } ))

  let top-margin = if title != none {
    sections_height + progress_bar_height + title_bar_height
  } else {
    sections_height + progress_bar_height
  };

  set page(
    margin: (top: top-margin, bottom: 1cm),
    header: header,
    footer: footer,
    background: background, 
    foreground: foreground
  )

  pl.slide({
    set align(horizon)
    set text(size: sns-polylux-template_size.at(here()), top-edge: 20pt, bottom-edge: 0pt)
    show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
    body
  })

  if not page-number { counter("logical-slide").update( n => n - 1 ) }
} )

#let focus-slide(
  new-sec      : none,
  page-number  : true,
  hide-section : false,
  background      : [],
  foreground      : [],
  body
) = context( {
  set page(
    margin: (top: 2.5cm, bottom: 0cm),
    footer: none,
    fill: sns-polylux-template_colormap.at(here()).at(1),
    background: background, 
    foreground: foreground
  )

  pl.slide({
    set align(horizon + center)
    set text(
      size: sns-polylux-template_size.at(here())*1.5,
      fill: sns-polylux-template_second-text-color.at(here()),
      style: "italic"
    )
    show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
    body
  })
  
  if not page-number { counter("logical-slide").update( n => n - 1 ) }
} )

#let empty-slide(
  background      : [],
  foreground      : [],
  body
) = context( {
  // HEADER
  let header = align(top, context( {
    let logo        = sns-polylux-template_logo-1.at(here())

    place(
      top + left,
      box(
        height: 2.5cm,
        if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
      )
    )
  } ))

  set page(
    margin: (top: 2.7cm, bottom: 0cm),
    header: header,
    footer: none,
    fill: sns-polylux-template_colormap.at(here()).at(1),
    background: background, 
    foreground: foreground
  )

  pl.slide({
    set align(horizon + center)
    set text(
      size: sns-polylux-template_size.at(here())*1.5,
      fill: sns-polylux-template_second-text-color.at(here()),
    )
    show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
    body
  })

  counter("logical-slide").update( n => n - 1 )
} )

#let new-section-slide(
  name,
  background      : [],
  foreground      : [],
)  = context( {
  // HEADER
  let header = align(top, context( {
    let logo        = sns-polylux-template_logo-1.at(here())

    place(
      top + left,
      box(
        height: 2.5cm,
        if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
      )
    )
  } ))

  set page(
    margin: (top: 2.7cm, bottom: 0cm),
    header: header,
    footer: none,
    fill: sns-polylux-template_colormap.at(here()).at(1),
    background: background, 
    foreground: foreground
  )

  // TOC
  /*
  let content = context( {
    pl.toolbox.all-sections( (sections, current) => {
    set text(weight: "regular")
    let over_current = false
    for i in sections {
      if (current == i) {[
        + #text(weight: "black", i)
      ]; over_current = true}
      else if (over_current) [
        + #text(weight: "thin", i)
      ]
      else [
        + #text(i)
      ]
    }
    } )
  } )
  */

  pl.slide({
    set align(horizon + center)
    set text(
      size: sns-polylux-template_size.at(here())*1.5,
      fill: sns-polylux-template_second-text-color.at(here()),
    )
    register-section(name)

    show: pad.with(20%)

    name 
    progress-bar()

  })

  counter("logical-slide").update( n => n - 1 )
} )

#let toc-slide(
  title           : none,
  background      : [],
  foreground      : [],
)  = context( {
  // HEADER
  let header = align(top, {
    let logo        = sns-polylux-template_logo-1.at(here())

    place(
      top + left,
      box(
        height: 2.5cm,
        if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
      )
    )
  } )

  set page(
    margin: (top: 2.7cm, bottom: 0cm),
    header: header,
    footer: none,
    fill: sns-polylux-template_colormap.at(here()).at(1),
    background: background, 
    foreground: foreground
  )

  // TOC
  let content = {
    if title != none { align(center,text(weight: "bold", title)); v(-0.2em) }
    pl.toolbox.all-sections( (sections, current) => {
    for i in sections [
      + #text(i)
    ]
    } )
  }

  pl.slide({
    set align(horizon + center)
    set text(
      size: sns-polylux-template_size.at(here())*1.5,
      fill: sns-polylux-template_second-text-color.at(here()),
    )

    show: box.with()
    set align(left)
    content
  })

  counter("logical-slide").update( n => n - 1 )
} )


