% Mark's handout style.
%
% Source is at https://git.betalupi.com/Mark/ormc-handouts


\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{ormc_handout}[2022/05/07 1.1.0 ORMC Handout]


% Boolean that determines solution behavior.
% If false, solutions and instructor notes are hidden.
\newif{\ifsolutions}
\solutionstrue

% Boolean that determines object numbering
% If true, the same counter is used for all objects.
\newif{\ifsinglenumbering}
\singlenumberingfalse

% Boolean. If true, don't number pages.
\newif{\ifnopagenumber}
\nopagenumberfalse

% Boolean. If true, show a smaller solutions warning
\newif{\ifshortwarning}
\shortwarningfalse

% Boolean. If true, do not show solution warning
\newif{\ifnowarning}
\nowarningfalse

% Declare and parse arguments
\DeclareOption{solutions}{\solutionstrue}
\DeclareOption{nosolutions}{\solutionsfalse}
\DeclareOption{singlenumbering}{\singlenumberingtrue}
\DeclareOption{nopagenumber}{\nopagenumbertrue}
\DeclareOption{shortwarning}{\shortwarningtrue}
\DeclareOption{nowarning}{\nowarningtrue}
\DeclareOption*{\ClassWarning{ormc_handout}{\CurrentOption ignored}}
\ProcessOptions\relax

% Based on article class
\LoadClass{article}
\makeatletter  % Allow commands with @ (\makeatother is at end of this file)

\newcommand\sbullet[1][.5]{\mathbin{\vcenter{\hbox{\scalebox{#1}{$\bullet$}}}}}

\renewcommand{\labelitemi}{$\sbullet$}
\renewcommand{\labelitemii}{$\cdot$}


% Hack for command-line arguments.
% To force a build with solutions, run
% latexmk
%	-synctex=1
%	-interaction=nonstopmode
%	-file-line-error
%	-outdir=%OUTDIR%
%	-xelatex
%	-jobname=%DOCFILE%.sol
%	-pdfxelatex="xelatex %O \"\\def\\argYesSolutions{1}\\input{%S}\""
%	%DOC%
%
% Or, make a new file with the contents
% \def\argYesSolutions{1}\input{<target file>}
% and build that with latex.
\ifdefined\argYesSolutions
	\solutionstrue
\else
	\ifdefined\argNoSolutions
		\solutionsfalse
	\fi
\fi




%%% PACKAGES %%%


% Set up page geometry.
% MUST BE DONE FIRST!
\RequirePackage{geometry}
\geometry{
	paper      = letterpaper,
	top        = 25mm,
	bottom     = 30mm,
	left       = 30mm,
	right      = 30mm,
	headheight = 75mm,
	footskip   = 15mm,
	headsep    = 75mm,
}

\RequirePackage{enumitem}  % list customization
\RequirePackage{xparse}    % Provides powerful macros via \NewDocumentCommand
\RequirePackage{xcolor}    % For colored text
\RequirePackage{tcolorbox} % For solution boxes
\RequirePackage{tikz}      % Used by \boxlinehack
\RequirePackage{comment}   % Used to hide solutions
\RequirePackage{fancyhdr}  % Header/Footer customization
\RequirePackage{adjustbox} % Used for title

\RequirePackage[
	left = ``,
	right = '',
	leftsub = `,
	rightsub = '
]{dirtytalk}

% Not used by this class, but likely to be used in documents
\RequirePackage{amsmath}
\RequirePackage{amssymb}
\RequirePackage{multicol}




%%% CONFIG %%%


% No paragraph indentation, no list item spacing,
% raggedright layout (hyphenation is excessive).
\setlength{\parindent}{0mm}
\setlist{noitemsep, topsep=0mm}
\raggedright

\renewcommand*{\thefootnote}{\arabic{footnote}}

% One space after a period.
\frenchspacing


% Fancyhdr setup
\pagestyle{fancy}
\fancyhf{}
\renewcommand{\headrulewidth}{0mm}

\ifnopagenumber
\else
	\fancyfoot[C]{\thepage}
\fi




%%% COMMANDS %%%


% Make a heading.
% Arguments:
%
% First: Top-left text
% Second: Top-right text
% Both are optional, but should only be provided TOGETHER.
%
% Third: Title
% Forth: author
\RenewDocumentCommand{\maketitle}{ d<> d<> m m } {
	\begin{adjustbox}{minipage=0.7\textwidth, margin=0pt \smallskipamount,center}
		\begin{center}

			\IfNoValueF{#1}{\textsc{#1}} \hfill \IfNoValueF{#2}{\textsc{#2}} \par
			\rule{\linewidth}{0.2mm} \par

			\huge
			#3 \par
			\normalsize
			\vspace{1ex}
			#4
			\rule{\linewidth}{0.2mm} \par

			% Instructor's handout warning
			\ifnowarning\else
			\ifsolutions
				% Short warning
				\ifshortwarning
					\begin{tcolorbox}[
						colback=white,
						colframe=red
					]
						\begin{center}
							\large
							\textcolor{red}{
								\textbf{Instructor's Handout}
							} \par
							\normalsize
						\end{center}
					\end{tcolorbox}
				\else
					% Regular warning
					\begin{tcolorbox}[
						colback=white,
						colframe=red
					]
						\begin{center}
							\large
							\textcolor{red}{
								\textbf{Instructor's Handout}
							} \par
							\normalsize
						\end{center}

						\vspace{1ex}

						\textcolor{red}{This file contains solutions and notes.}

						\textcolor{red}{Compile with the ``nosolutions'' flag before distributing.}
					\end{tcolorbox}
				\fi
			\fi\fi

		\end{center}
	\end{adjustbox}
}


% Helper command that creates a label with custom text.
% First arg: label name
% Second arg: custom text
\newcommand{\customlabel}[2]{%
	\protected@write \@auxout {}{
		\string \newlabel {#1}{{#2}{}}
	}
}


% Commands for problems, theorems, and definitions
%
% Each of these take two arguments. For example:
%
% \problem{} makes an unnamed problem
% \problem{Division} makes a named problem
% \problem{}<gcd>
%   makes a problem and a label "problem:gcd"
%   that gives text "Problem X" when referenced.

\newcounter{section_counter}
\newcounter{problempartcounter}

\ifsinglenumbering
	\newcounter{object_counter}

	\def\problemcounter{object_counter}
	\def\theoremcounter{object_counter}
	\def\definitioncounter{object_counter}
	\def\examplecounter{object_counter}
	\def\propositioncounter{object_counter}
\else
	\newcounter{problem_counter}
	\newcounter{theorem_counter}
	\newcounter{definition_counter}
	\newcounter{example_counter}
	\newcounter{proposition_counter}

	\def\problemcounter{problem_counter}
	\def\theoremcounter{theorem_counter}
	\def\definitioncounter{definition_counter}
	\def\examplecounter{example_counter}
	\def\propositioncounter{proposition_counter}
\fi


% Generic object command.
% First arg: counter name (mandatory)
% Second arg: object type (optional)
% Third arg: object title (mandatory, can be empty)
%
% If the second argument is ommited, the counter is hidden
% and only the object title is shown. For example:
% \@object{counter}[Problem]{Example Problem} -> Problem 1: Example Problem
% \@object{counter}{Example Problem} -> Example Problem
%
% Only used internally (See following definitions)
\NewDocumentCommand{\@object}{ m d[] m}{
	\stepcounter{#1}
	\vspace{3mm}
	\IfNoValueTF{#2} {
		{\bf\normalsize #3}
	} {
		{\bf\normalsize #2 \arabic{#1}:\IfNoValueF{#3}{ #3}}
	}
}

% Generic object.
% Does the same thing as \problem, \theorem, etc, but with no counter.
\NewDocumentCommand{\generic}{ m d<> }{
	\vspace{3mm}
	{\bf\normalsize #1} \\lat*

	\IfNoValueF{#2}{
		\customlabel{#2}{#1}
	}
}

% If not starred, text is "Part X: <title>"
% If starred, text is "<title>"
\RenewDocumentCommand{\section}{ s m d<> }{
	\stepcounter{section_counter}
	\vspace{8mm}
	\IfBooleanTF{#1}{
		{\bf\Large \hfill #2 \hfill}
		\IfNoValueF{#3}{\customlabel{#3}#2} \\*
	} {
		{\bf\Large \hfill Part \arabic{section_counter}\IfNoValueF{#2}{: #2} \hfill}
		\IfNoValueF{#3}{\customlabel{#3}Part \arabic{section_counter}} \\*
	}
	\vspace{2mm}
}


\RenewDocumentCommand{\paragraph}{}{
	\hspace{1cm}
}

\NewDocumentCommand{\problem}{ m d<> }{
	\setcounter{problempartcounter}{0}

	\@object{\problemcounter}[Problem]{#1}
	\IfNoValueF{#2}{
		\customlabel{#2}{Problem \arabic{\problemcounter}}
		\customlabel{NUM:#2}{\arabic{\problemcounter}}
	} \\*
}

\NewDocumentCommand{\problempart}{ m d<> }{
	\@object{problempartcounter}[Part]{#1}
	\IfNoValueF{#2}{
		\customlabel
			{#2}
			{Problem \arabic{\problemcounter}\alph{problempartcounter}}
		\customlabel{NUM:#2}{\arabic{\problemcounter}\alph{problempartcounter}}
	} \\*
}

\NewDocumentCommand{\definition}{ m d<> }{
	\@object{\definitioncounter}[Definition]{#1}
	\IfNoValueF{#2}{
		\customlabel{#2}{Definition \arabic{\definitioncounter}}
		\customlabel{NUM:#2}{\arabic{\definitioncounter}}
	} \\*
}

\NewDocumentCommand{\theorem}{ m d<> }{
	\@object{\theoremcounter}[Theorem]{#1}
	\IfNoValueF{#2}{
		\customlabel{#2}{Theorem \arabic{\theoremcounter}}
		\customlabel{NUM:#2}{\arabic{\theoremcounter}}
	} \\*
}

\NewDocumentCommand{\proposition}{ m d<> }{
	\@object{\propositioncounter}[Proposition]{#1}
	\IfNoValueF{#2}{
		\customlabel{#2}{Proposition \arabic{\propositioncounter}}
		\customlabel{NUM:#2}{\arabic{\propositioncounter}}
	} \\*
}

\NewDocumentCommand{\example}{ m d<> }{
	\@object{\examplecounter}[Example]{#1}
	\IfNoValueF{#2}{
		\customlabel{#2}{Example \arabic{\examplecounter}}
		\customlabel{NUM:#2}{\arabic{\examplecounter}}
	} \\*
}


% Solution environment.
% examplesolution environment is always shown (useful for example problems)
% solution environments do the same thing, but are hidden when the [nosolutions] flag is passed.
\newenvironment{examplesolution} {
	\begin{tcolorbox}[
		colback=white,
		colframe=gray!75!black,
		title={\textbf{Example Solution}}
	]
}{
	\end{tcolorbox}
}

\def\ORMCbgcolor{white}

% \if isn't parsed inside of LaTeX environents,
% so we have to use the comment package.
\newenvironment{@shown_solution} {
	\def\ORMCbgcolor{red!5!white}
	\begin{tcolorbox}[
		colback=red!5!white,
		colframe=red!75!black,
		title={\textbf{Solution}}
	]
	\raggedright
}{
	\end{tcolorbox}
}

\newenvironment{@shown_note} {
	\def\ORMCbgcolor{cyan!5!white}
	\begin{tcolorbox}[
		colback=cyan!5!white,
		colframe=cyan!75!black,
		title={\textbf{Note for Instructors}}
	]
	\raggedright
}{
	\end{tcolorbox}
}

% tcolorbox only give us two sections.
% This macro makes a macro \linehack that draws
% lines across a tcolorbox.
%
% Inside every environment that needs a
% \linehack macro, put \@makelinehack{color}.
\newcommand{\@makelinehack}[1]{
	\newcommand{\linehack}{
		\begin{tikzpicture}
			\path[use as bounding box]
				(0, 0)
				--
				(\linewidth, 0);

			\draw[
				color=#1,
				dashed,
				dash phase=1mm
			]
			(
				0 - \kvtcb@leftlower-\kvtcb@boxsep,
				0
			) -- (
				\linewidth + \kvtcb@rightlower + \kvtcb@boxsep,
				0
			);
		\end{tikzpicture} \par
		\vspace{2mm}
	}
}

\ifsolutions
	\newenvironment{solution}{
		\@makelinehack{red!75!black}
		\begin{@shown_solution}
	} {
		\end{@shown_solution}
	}
	\newenvironment{instructornote}{
		\@makelinehack{cyan!75!black}
		\begin{@shown_note}
	} {
		\end{@shown_note}
	}
\else
	\excludecomment{solution}
	\excludecomment{instructornote}
\fi


\NewDocumentCommand{\note}{ d<> m }{
	\IfNoValueTF{#1} {
		\textcolor{gray}{#2} \par
	} {
		\textcolor{gray}{\textit{#1:} #2} \par
	}
}

\NewDocumentCommand{\hint}{ m }{
	\note<Hint>{#1}
}

\makeatother