#show heading: set text(font: "New Computer Modern")
#show link: underline

// smartypants and latex compatibility
#show "--": [#sym.dash.en]
#show "---": [#sym.dash.em]
#show "\&": [#sym.amp]

// 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 sel_word_lang(de: "", en:"") = {
    if 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 by_client(experience:()) = {
    let by_client = (:)

    for item in experience {
        let client = item.place.at(lang)
        if client not in by_client {
            by_client.insert(client, ())

        }
        by_client.at(client).push( (item.title.at(lang), item.date.at(lang)) )
    }

    for (client, jobs) in by_client {
        [*#client*:]
        for j in jobs {
            [- #j.at(0) #h(1fr) #j.at(1)]
        }
    }
}

#let by_experience_type(type:(), experience:()) = {
    let by_ty = (:)
    for (id, desc) in type {
        let matching_exp_items = ();
        // for item in experience {
        //     [itemtypeid: #item.typeid, id: #id]
        //     if item.typeid == id {
        //         matching_exp_items.push(item)
        //     }
        // }
        let matching_exp_items = experience.filter(item =>
        int(item.typeid) == int(id))
        [=== _#desc.at(lang)_]
        by_client(experience: matching_exp_items)
    }
}

#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 [)]
        })
    }
}

#let resume(contents) = {
    set text(lang: lang)

    let date_formatting = {
        if lang == "de" {
            "[day]. [month repr:long] [year]"
        } else {
            "[month repr:long] [day], [year]"
        }
    }
    set page(
        paper: "a4",
        margin: (x: 0.9cm, y: 1.3cm),
        footer: [
            #set text(
              fill: luma(200),
              size: 8pt,
            )
            #_columns_3[
                #smallcaps[#datetime.today().display(date_formatting)]
            ][
                #smallcaps[#contents.about.fullname]
            ][
                #context counter(page).display()
            ]
        ],
    )

    set par(justify: true)

    header(contents.about)

    let body = {
//        if "summary" in contents {
//            section(title:"", {
//                contents.summary.at(lang)
//            })
//        };

        if "experience" in contents {
            let title = sel_word_lang(en:"Professional Experience", de:"Berufserfahrung")
            section(title: title)[]
            by_experience_type(experience: contents.experience, type: contents.experience_types)
        }

        if "education" in contents {
            let title = sel_word_lang(en:"Education", de:"Ausbildung")
            section(title: title, entries:contents.thesis + contents.education)[]
        }

//        if "volunteering" in contents {
//            let title = sel_word_lang(en:"Volunteer Work", de:"Ehrenamt")
//            section(title: title, entries:contents.volunteering)[]
//        }
//
//        if "skills" in contents {
//            let title = sel_word_lang(en:"Qualifications", de:"Qualifikationen")
//            section(title: title, {
//                skill_item(item:contents.skills)
//            })
//        }
//
//        if "languages" in contents {
//            let title = sel_word_lang(en:"Languages", de:"Sprachen")
//            section(title: title, {
//                skill_item(item:contents.languages)
//            })
//        }
    }

    let sidebar = {
        if "volunteering" in contents {
            let title = sel_word_lang(en:"Volunteer Work", de:"Ehrenamt")
            [== #title]
            for e in contents.volunteering {
                [
                - *#e.title.at(lang)* (#e.date.at(lang))
                   #par(e.bullets.at(0).at(lang)) \
                ]
            }
        }

        if "languages" in contents {
            let title = sel_word_lang(en:"Languages", de:"Sprachen")
            [== #title]
            skill_item(item:contents.languages, is_sidebar: true)
            [\ ]
        }

        if "skills" in contents {
            let title = sel_word_lang(en:"Qualifications", de:"Kenntnisse")
            [== #title]
            skill_item(item:contents.skills, is_sidebar: true)
        }
    }

    let margin = 1pt
    grid(
        columns: (2fr, 1fr),
        block(outset: 0pt, inset: (top: 0.4 * margin, right: 0pt, rest: margin), stroke: none, width: 100%, {
            set block(above: 10pt)
            show heading.where(level: 1): it => style(s => {
              let h = text(size: 18pt, upper(it))
              let dim = measure(h, s)
              stack(
                dir: ltr,
                h,
                place(
                  dy: 7pt,
                  dx: 10pt,
                  horizon + left,
                  line(stroke: accent-color, length: 100% - dim.width - 10pt)
                ),
              )
            })
            body
        }),
        align(right, block(fill: luma(250), width: 90%,
        {
          v(15pt)
          set block(inset: (left: 20 * margin, right: 20 * margin))
          show heading: it => align(right, upper(it))
          set list(marker: "")
          show list: it => {
            set par(justify: false)
            align(right, block(it))
          }
        sidebar
          v(15pt)
        }))
    )

}

#resume(
    yaml("content.yml")
)