% SPDX-FileCopyrightText: 2026 Claire Tam <claire.tam@student.adelaide.edu.au>
% SPDX-FileCopyrightText: 2026 fractuscontext <106440141+fractuscontext@users.noreply.github.com>
%
% SPDX-License-Identifier: LPPL-1.3c

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{user-persona}[2026/10/28 v2.0 Interactive Persona Package]

\RequirePackage{graphicx}
\RequirePackage[many]{tcolorbox}
\RequirePackage{xcolor}
\RequirePackage{etoolbox}
\RequirePackage{enumitem}
\RequirePackage{tabularx}
\RequirePackage{fontawesome5}
\RequirePackage{pgfopts}

\definecolor{PersonaDark}{HTML}{354254}       % Main header background
\definecolor{PersonaQuoteBg}{HTML}{FFF8DF}     % Quote background (light yellow)
\definecolor{PersonaQuoteBorder}{HTML}{F6B762} % Quote border (orange)
\definecolor{PersonaGreen}{HTML}{5CA662}       % Goals / Core Needs
\definecolor{PersonaBlue}{HTML}{5D86D6}        % Behaviours
\definecolor{PersonaRed}{HTML}{E26556}         % Pain Points
\definecolor{PersonaGrey}{HTML}{8E94A0}        % Context outline
\definecolor{PersonaTrack}{HTML}{E3E5E9}       % Scale track / empty rating dot

\colorlet{PersonaHeaderBg}{PersonaDark}
\colorlet{PersonaHeaderText}{white}

\makeatletter
% chktex-file 1 (`\foo@bar ` spacing is intentional in package code)

% --- Options ---
% Usable as package options, via \personasetup{...}, or per persona
% via \begin{persona}[...]{Name}.
\newif\ifpersona@uppercase
\pgfkeys{
  /persona/.is family, /persona,
  label/.store in=\persona@label,
  uppercase/.is if=persona@uppercase,
  leftwidth/.store in=\persona@leftwidth,
  gap/.store in=\persona@gap,
  headercolor/.code={\colorlet{PersonaHeaderBg}{#1}},
  headertextcolor/.code={\colorlet{PersonaHeaderText}{#1}},
  quotecolor/.code={\colorlet{PersonaQuoteBg}{#1}},
  quoteborder/.code={\colorlet{PersonaQuoteBorder}{#1}},
  accent/.store in=\persona@accent,
  label=User Persona,
  uppercase=true,
  leftwidth=0.35,
  gap=0.04,
  accent=PersonaDark,
}
\ProcessPgfPackageOptions{/persona}

\newcommand{\personasetup}[1]{\pgfkeys{/persona,#1}}

% --- Box Styles ---
\tcbset{
  personasectionbox/.style={
    colback=white,
    boxrule=1pt,
    arc=1.5mm,
    left=3mm, right=3mm, top=1mm, bottom=2mm,
    fonttitle=\bfseries\sffamily\footnotesize,
    colbacktitle=white,
    titlerule=0pt,
    bottomtitle=0mm, toptitle=2.5mm,
    boxsep=0pt,
    before skip=2mm, after skip=1mm
  }
}

\newenvironment{persona}[2][]{%
  \pgfkeys{/persona,#1}%
  \def\@personaname{#2}%
  \def\@personaphoto{}%
  \def\@personaquote{}%
  \def\@personafacts{}%
  \def\@personaleftcards{}%
  \def\@personarightcards{}%
  \def\@personaspancards{}%
}{%
  \noindent
  \begin{tcolorbox}[colback=PersonaHeaderBg, coltext=PersonaHeaderText, sharp corners, boxrule=0pt, fontupper=\bfseries\large\sffamily, left=2mm, top=2.5mm, bottom=2.5mm, nobeforeafter]
    \ifpersona@uppercase
      \ifx\persona@label\@empty\else\MakeUppercase{\persona@label}: \fi\MakeUppercase{\@personaname} % chktex 13
    \else
      \ifx\persona@label\@empty\else\persona@label: \fi\@personaname % chktex 13
    \fi
  \end{tcolorbox}
  % Keep the header on the same page as the columns
  \par\nopagebreak\vspace{3mm}

  \noindent
  \begin{minipage}[t]{\persona@leftwidth\textwidth}
    \vspace{0pt}
    \ifx\@personaphoto\@empty\else
      \IfFileExists{\@personaphoto}{%
        \includegraphics[width=\linewidth]{\@personaphoto}%
      }{%
        \begin{tcolorbox}[width=\linewidth, height=\linewidth, colback=gray!15, colframe=gray!40, halign=center, valign=center, arc=0mm, boxrule=1pt]
          \sffamily\scriptsize\color{gray!70} Image not found:\\ \texttt{\@personaphoto}
        \end{tcolorbox}%
      }%
    \fi

    \vspace{3mm}\par

    \begingroup
    \renewcommand{\arraystretch}{1.4}%
    \sffamily\scriptsize
    \begin{tabularx}{\linewidth}{@{} l >{\raggedright\arraybackslash}X @{}}
      \@personafacts%
    \end{tabularx}
    \endgroup

    \@personaleftcards%

  \end{minipage}%
  \hfill
  \begin{minipage}[t]{\dimexpr\textwidth-\persona@leftwidth\textwidth-\persona@gap\textwidth\relax}
    \vspace{0pt}

    \ifx\@personaquote\@empty\else
      \begin{tcolorbox}[colback=PersonaQuoteBg, colframe=PersonaQuoteBorder, boxrule=0.8pt, arc=1.5mm, left=3.5mm, right=3.5mm, top=2.5mm, bottom=2.5mm, before skip=0pt, after skip=2.5mm]
        \sffamily\itshape\footnotesize \@personaquote%
      \end{tcolorbox}
    \fi

    \@personarightcards%
  \end{minipage}

  \par
  \@personaspancards%
  \par\vspace{5mm}
}

\newcommand{\personaphoto}[1]{\def\@personaphoto{#1}}
\newcommand{\personaquote}[1]{\def\@personaquote{#1}}
\newcommand{\personafact}[2]{\appto\@personafacts{\textbf{#1:} & #2 \\}}

% \persona@box[tcb options]{Title}{Color}{Content}
\newcommand{\persona@box}[4][]{%
  \begin{tcolorbox}[personasectionbox, #1, colframe=#3, coltitle=#3, title={\MakeUppercase{#2}}]
    \def\persona@accent{#3}%
    \scriptsize\sffamily #4
  \end{tcolorbox}%
}

% \persona@addcard{position}{{Title}{Color}{Content}}
% Span cards sit outside the columns, so they may break across pages.
\def\persona@pos@left{}
\def\persona@pos@right{}
\def\persona@pos@span{}
\newcommand{\persona@addcard}[2]{%
  \ifcsname persona@pos@#1\endcsname
    \ifstrequal{#1}{span}{%
      \appto\@personaspancards{\persona@box[breakable]#2}%
    }{%
      \csappto{@persona#1cards}{\persona@box#2}%
    }%
  \else
    \PackageError{user-persona}{Unknown card position `#1'}{%
      Use left, right or span. The card has been placed on the right.}%
    \appto\@personarightcards{\persona@box#2}%
  \fi
}

\newcommand{\personasection}[4][right]{%
  \persona@addcard{#1}{{#2}{#3}{%
    \begin{itemize}[leftmargin=3.5mm, nosep, itemsep=3pt, label={\tiny$\bullet$}]
      #4
    \end{itemize}%
  }}%
}

\newcommand{\personacard}[4][right]{%
  \persona@addcard{#1}{{#2}{#3}{#4}}%
}

\newcommand{\personacontext}[3][left]{\personacard[#1]{#2}{PersonaGrey}{#3}}

\newcommand{\personapill}[1]{%
  \tcbox[on line, tcbox raise base, colback=gray!15, colframe=gray!15, arc=2mm, boxrule=0pt, left=2mm, right=2mm, top=1mm, bottom=1mm, boxsep=0pt]{\sffamily\scriptsize #1}\enskip%
}

\newcommand{\personabrand}[2][img]{%
  \tcbox[on line, tcbox raise base, colback=white, colframe=gray!30, arc=1mm, boxrule=0.5pt, left=1.5mm, right=1.5mm, top=1mm, bottom=1mm, boxsep=0pt]{%
    \ifstrequal{#1}{img}{%
      \IfFileExists{#2}{%
        \raisebox{-0.2\height}{\includegraphics[height=3.5mm, keepaspectratio]{#2}}%
      }{%
        \sffamily\tiny Missing%
      }%
    }{%
      \sffamily\raisebox{-0.1\height}{#2}%
    }%
  }\enskip%
}

% --- Scales & Ratings ---
% Colour defaults to the enclosing \personacard frame colour (else `accent').

% \personascale[color]{Left label}{Right label}{value, 0 to 1}
\newcommand{\personascale}[4][\persona@accent]{%
  \par\noindent
  {\sffamily\scriptsize #2\hfill #3}\par\nointerlineskip\vspace{1mm}%
  \pgfmathsetlengthmacro\persona@scalex{1.2mm + (#4)*(\linewidth-2.4mm)}% chktex 36
  \noindent\begin{tikzpicture}
    \useasboundingbox (0,-1.2mm) rectangle (\linewidth,1.2mm);
    \fill[PersonaTrack, rounded corners=0.4mm] (0,-0.4mm) rectangle (\linewidth,0.4mm);
    \fill[fill=#1, rounded corners=0.4mm] (0,-0.4mm) rectangle (\persona@scalex,0.4mm);
    \filldraw[fill=white, draw=#1, line width=0.8pt] (\persona@scalex,0) circle (1.1mm);
  \end{tikzpicture}% chktex 31
  \par\vspace{1.5mm}%
}

% \personarating[color]{Label}{value}{max}
\newcommand{\personarating}[4][\persona@accent]{%
  \par\noindent
  {\sffamily\scriptsize #2}\hfill
  {\tiny\foreach \persona@i in {1,...,#4}{% chktex 11
    \ifnum\persona@i>#3\relax
      \textcolor{PersonaTrack}{\faCircle}%
    \else
      \textcolor{#1}{\faCircle}%
    \fi
    \ifnum\persona@i<#4\relax\,\fi
  }}\par\vspace{1mm}%
}

\makeatother
\endinput
