% Copyright (C) 2024 Mark (mark@betalupi.com)
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see <https://www.gnu.org/licenses/>.

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{ormc_handout}[2023/05/29 2.0.2 ORMC Handout]




% ------------------ %
% Option Definitions %
% ------------------ %

% Standard LaTeX
\newcommand\@ptsize{}
\@twocolumnfalse
\@twosidefalse
\@mparswitchfalse
% ORMC-specific
\newif{\if@solutions} % If false, solutions and instructor notes are hidden.
\newif{\if@singlenumbering} % If true, the same counter is used for all objects.
\newif{\if@nopagenumber} % If true, don't number pages.
\newif{\if@shortwarning} % If true, show a smaller solutions warning
\newif{\if@nowarning} % If true, do not show solution warning
\newif{\if@unfinished} % If true, show an "unfinished" warning at the top of each page

% Standard LaTeX options
\DeclareOption{10pt}{\renewcommand\@ptsize{0}}
\DeclareOption{11pt}{\renewcommand\@ptsize{1}}
\DeclareOption{12pt}{\renewcommand\@ptsize{2}}
% ORMC-specific options
\DeclareOption{solutions}{\@solutionstrue}
\DeclareOption{nosolutions}{\@solutionsfalse}
\DeclareOption{multinumbering}{\@singlenumberingfalse}
\DeclareOption{singlenumbering}{\@singlenumberingtrue}
\DeclareOption{pagenumber}{\@nopagenumberfalse}
\DeclareOption{nopagenumber}{\@nopagenumbertrue}
\DeclareOption{longwarning}{\@shortwarningfalse}
\DeclareOption{shortwarning}{\@shortwarningtrue}
\DeclareOption{showwarning}{\@nowarningfalse}
\DeclareOption{hidewarning}{\@nowarningtrue}
\DeclareOption{unfinished}{\@unfinishedtrue}
\DeclareOption*{\ClassWarning{ormc_handout}{\CurrentOption ignored}}

\@unfinishedfalse
\ExecuteOptions{
	10pt,
	solutions,
	multinumbering,
	pagenumber,
	longwarning,
	yeswarning
}

\ProcessOptions

% Set letterpaper by default.
% This is overridden by geometry anyway,
% so we don't need an option.
\setlength\paperheight{11in}
\setlength\paperwidth{8.5in}
\input{size1\@ptsize.clo}

% Hack to allow script option override.
% To force a build with solutions, compile a file containing the following:
%	`\def\argYesSolutions{1}\input{<target file>}`
\ifdefined\argYesSolutions\@solutionstrue\fi
\ifdefined\argNoSolutions\@solutionsfalse\fi








% ------------------------------- %
% Minimal LaTeX class             %
% Based on article.cls,           %
%    version 2022/07/02 v1.4n     %
% ------------------------------- %

% Lengths
\setlength\lineskip{1\p@}
\setlength\normallineskip{1\p@}
\renewcommand\baselinestretch{}
\setlength\parskip{9\p@ \@plus \p@}
\@lowpenalty 51
\@medpenalty 151
\@highpenalty 301

\setlength\leftmargini{2.5em}
\leftmargin\leftmargini
\setlength\leftmarginii{2.2em}
\setlength\leftmarginiii{1.87em}
\setlength\leftmarginiv{1.7em}
\setlength\leftmarginv{1em}
\setlength\leftmarginvi{1em}
\setlength\labelsep{.5em}
\setlength\labelwidth{\leftmargini}
\addtolength\labelwidth{-\labelsep}
\@beginparpenalty -\@lowpenalty
\@endparpenalty -\@lowpenalty
\@itempenalty -\@lowpenalty

\setlength\arraycolsep{5\p@}
\setlength\tabcolsep{6\p@}
\setlength\arrayrulewidth{.4\p@}
\setlength\doublerulesep{2\p@}
\setlength\tabbingsep{\labelsep}
\skip\@mpfootins = \skip\footins
\setlength\fboxsep{3\p@}
\setlength\fboxrule{.4\p@}

\newcommand\@pnumwidth{1.55em}
\newcommand\@tocrmarg{2.55em}
\newcommand\@dotsep{4.5}

\setlength\columnsep{10\p@}
\setlength\columnseprule{0\p@}


% Counters
\setcounter{topnumber}{2}
\renewcommand\topfraction{.7}
\setcounter{bottomnumber}{1}
\renewcommand\bottomfraction{.3}
\setcounter{totalnumber}{3}
\renewcommand\textfraction{.2}
\renewcommand\floatpagefraction{.5}
\setcounter{dbltopnumber}{2}
\renewcommand\dbltopfraction{.7}
\renewcommand\dblfloatpagefraction{.5}
%\setcounter{secnumdepth}{3}


% Enum labels
\renewcommand\theenumi{\@arabic\c@enumi}
\renewcommand\theenumii{\@alph\c@enumii}
\renewcommand\theenumiii{\@roman\c@enumiii}
\renewcommand\theenumiv{\@Alph\c@enumiv}
\newcommand\labelenumi{\theenumi.}
\newcommand\labelenumii{(\theenumii)}
\newcommand\labelenumiii{\theenumiii.}
\newcommand\labelenumiv{\theenumiv.}
\renewcommand\p@enumii{\theenumi}
\renewcommand\p@enumiii{\theenumi(\theenumii)}
\renewcommand\p@enumiv{\p@enumiii\theenumiii}
\newcommand\labelitemi{\labelitemfont \textbullet}
\newcommand\labelitemii{\labelitemfont \bfseries \textendash}
\newcommand\labelitemiii{\labelitemfont \textasteriskcentered}
\newcommand\labelitemiv{\labelitemfont \textperiodcentered}
\newcommand\labelitemfont{\normalfont}

% Required by enumitem, not sure why.
\newenvironment{description}{%
	\list{}{\labelwidth\z@ \itemindent-\leftmargin\let\makelabel\descriptionlabel}%
}{\endlist}

\newcommand*\descriptionlabel[1]{\hspace\labelsep\normalfont\bfseries #1}


% Font switching
\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm}
\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf}
\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt}
\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf}
\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit}
\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl}
\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc}
\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal}
\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal}


% Figures and tables
\newcommand\figurename{Figure}
\newcommand\tablename{Table}
\newcounter{figure}
\renewcommand \thefigure {\@arabic\c@figure}
\def\fps@figure{tbp}
\def\ftype@figure{1}
\def\ext@figure{lof}
\def\fnum@figure{\figurename\nobreakspace\thefigure}
\newenvironment{figure}{\@float{figure}}{\end@float}
\newenvironment{figure*}{\@dblfloat{figure}}{\end@dblfloat}
\newcounter{table}
\renewcommand\thetable{\@arabic\c@table}
\def\fps@table{tbp}
\def\ftype@table{2}
\def\ext@table{lot}
\def\fnum@table{\tablename\nobreakspace\thetable}
\newenvironment{table}{\@float{table}}{\end@float}
\newenvironment{table*}{\@dblfloat{table}}{\end@dblfloat}

\newlength\abovecaptionskip
\newlength\belowcaptionskip
\setlength\abovecaptionskip{10\p@}
\setlength\belowcaptionskip{0\p@}

\long\def\@makecaption#1#2{%
	\vskip\abovecaptionskip
	\sbox\@tempboxa{#1: #2}%
	\ifdim \wd\@tempboxa >\hsize
		#1: #2\par
	\else
		\global \@minipagefalse
		\hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
	\fi
	\vskip\belowcaptionskip%
}
\newcommand*\l@figure{\@dottedtocline{1}{1.5em}{2.3em}}
\let\l@table\l@figure


% Miscellaneous
\newcommand\newblock{\hskip .11em\@plus.33em\@minus.07em}
\let\@openbib@code\@empty

\newcommand\@idxitem{\par\hangindent 40\p@}
\newcommand\subitem{\@idxitem \hspace*{20\p@}}
\newcommand\subsubitem{\@idxitem \hspace*{30\p@}}
\newcommand\indexspace{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax}
\renewcommand\footnoterule{%
	\kern-3\p@
	\hrule\@width.4\columnwidth
	\kern2.6\p@%
}
\newcommand\@makefntext[1]{%
	\parindent 1em%
	\noindent
	\hb@xt@1.8em{\hss\@makefnmark}#1%
}

\def\today{%
	\ifcase\month\or
		January\or
		February\or
		March\or
		April\or
		May\or
		June\or
		July\or
		August\or
		September\or
		October\or
		November\or
		December
	\fi%
	\space\number\day, \number\year
}

\pagenumbering{arabic}
\raggedbottom
\onecolumn








% ------------ %
% Minor Tweaks %
% ------------ %

% We probably don't need enumitem for this.
% TODO: apply these edits above, in plain LaTeX.

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

\renewcommand{\labelitemi}{$\sbullet$}
\renewcommand{\labelitemii}{$\cdot$}
\renewcommand{\labelenumi}{\textbf{\Alph{enumi}:}}










% ------------- %
% Package Setup %
% ------------- %


% Set up page geometry.
% MUST BE DONE FIRST!
% TODO: can we do this with plain tex?
\RequirePackage{geometry}
\geometry{
	paper      = letterpaper,
	top        = 25mm,
	bottom     = 30mm,
	left       = 30mm,
	right      = 30mm,
	headheight = 75mm,
	footskip   = 15mm,
	headsep    = 75mm,
}

\RequirePackage{enumitem}  % List customization
\RequirePackage{etoolbox}  % For utilities like \undef
\RequirePackage{xparse}    % For \NewDocumentCommand and etc
\RequirePackage{xcolor}    % For colored text
\RequirePackage{tikz}      % Used by \boxlinehack
\RequirePackage{comment}   % Used to hide solutions
\RequirePackage{bophook}   % Call a command on every page
\RequirePackage{tcolorbox} % For solution boxes
\RequirePackage{hyperref}  % For custom references & clickable links
\tcbuselibrary{breakable}  % Allows tcolorboxes to break across pages
\tcbuselibrary{skins}      % Allows additional tcolorbox customization
\usetikzlibrary{calc}

\RequirePackage[ % Provides \say{} for quoted text.
	left = ``,
	right = '',
	leftsub = `,
	rightsub = '
]{dirtytalk}

% Not used by this class, but likely to be used in documents
\RequirePackage{amsmath}
\RequirePackage{amssymb}
\RequirePackage{tabto}
\TabPositions{1cm, 2cm, 3cm, 4cm, 5cm, 6cm, 7cm, 8cm}

% Colorlinks must be false.
% if it is set, references inside hints
% will not be the correct color!
\hypersetup{
	hidelinks,
	colorlinks=false,
	%pdftitle={title},
	%pdfauthor={Mark},
	%pdfcreator={Mark}
}


\definecolor{ored}{HTML}{D62121}
\definecolor{ogrape}{HTML}{9C36B5}
\definecolor{ocyan}{HTML}{2288BF}
\definecolor{oteal}{HTML}{12B886}
\definecolor{ogreen}{HTML}{37B26D}
\definecolor{oblue}{HTML}{1C7ED6}

\colorlet{red}{ored}
\colorlet{green}{ogreen}
\colorlet{blue}{oblue}
\colorlet{teal}{oteal}
\colorlet{cyan}{ocyan}


\if@unfinished
	\AtBeginPage{%
		\begin{tikzpicture}[overlay, remember picture]
			\path
				(current page.north) ++ (0, -1)
				node[
					anchor=center,
					draw,
					below,
					text=ored,
					draw=ored,
					fill=white,
					inner sep = 2mm,
					line width = 0.6mm,
				] {
					\textbf{Incomplete Handout:}
					this handout is not done, it may need edits!
				}
			;
		\end{tikzpicture}
	}
\fi







% ----------- %
% Style Setup %
% ----------- %

\if@nopagenumber
	\pagestyle{empty}
\else
	\pagestyle{plain}
\fi

\renewcommand*{\thefootnote}{\arabic{footnote}}
\setlength{\parindent}{0mm}
\setlist{noitemsep, topsep=0mm}
\raggedright
\frenchspacing












% ------------- %
% Handout Title %
% ------------- %

% These are in LaTeX by default, but we don't use them here.
% Undef them to avoid confusion.
\undef\thanks
\undef\author
\undef\date
\undef\and

% Additional title parameters
\def\@subtitle{\relax}
\def\@uptitlel{\relax}
\def\@uptitler{\relax}
\newcommand{\subtitle}[1]{\gdef\@subtitle{#1}}
\newcommand{\uptitlel}[1]{\gdef\@uptitlel{#1}}
\newcommand{\uptitler}[1]{\gdef\@uptitler{#1}}

\newcommand{\@shortwarning}{
	\begin{tcolorbox}[
		enhanced,
		breakable,
		colback=white,
		colframe=ored,
		boxrule=0.6mm,
		arc=0mm,
		outer arc=0mm,
	]
		\large\centering\color{ored}
		\textbf{Instructor's Handout} \par
	\end{tcolorbox}
}

% digital boxes may look better with:
%	drop shadow=gray,
%	smart shadow arc=false

\newcommand{\@longwarning}{
	\begin{tcolorbox}[
		enhanced,
		breakable,
		colback=white,
		colframe=ored,
		boxrule=0.6mm,
		arc=0mm,
		outer arc=0mm,
	]
		\color{ored}
		\begingroup
			\large\centering
			\textbf{Instructor's Handout} \par
		\endgroup
		\vspace{1ex}
		This file contains solutions and notes. \par
		Compile with the ``nosolutions'' flag before distributing. \par
		Click \href{https://betalupi.com/handouts}{\texttt{[here]}}
		for the latest version of this handout. \par
	\end{tcolorbox}
}

% hyperref already defines maketitle.
\renewcommand{\maketitle}{
	\begingroup
	\centering
	\begin{minipage}{0.7\textwidth}
		\centering

		% Left and right headers (uptitle)
		\if\@uptitlel\relax\else\textsc{\@uptitlel}\fi \hfill\null%
		\if\@uptitler\relax\else\textsc{\@uptitler}\fi \par

		% Main title
		\rule{\linewidth}{0.2mm} \par
		\vspace{4mm}
		{\huge \@title} \par
		\if\@subtitle\relax\else\vspace{2mm} \@subtitle \par\fi
		\vspace{1mm}
		\rule{\linewidth}{0.2mm} \par

		% Solution warning
		\if@nowarning\else\if@solutions%
			\if@shortwarning \@shortwarning%
			\else \@longwarning%
		\fi\fi\fi
	\end{minipage} \par
	\vspace{2ex}
	\endgroup
}








% ---------------- %
% Handout Sections %
% ---------------- %

% Helper command that creates a label with custom text.
% Args: label name, custom text
%
% newlabel is redefined by hyperref,
% and its second arg takes two parts without hyperref and four with it.
\newcommand{\@customlabel}[2]{%
	\@ifpackageloaded{hyperref}{%
		% This is broken
		\@bsphack
		\begingroup
			\def\label@name{#1}%
			\def\@currentlabel{#2}%
			\label@hook
			\protected@write\@auxout{}{%
				\string\newlabel{#1}{%
					{\@currentlabel}%
					{\thepage}%
					{\@currentlabelname}%
					{\@currentHref}%
					{}%
				}%
			}%
		\endgroup
		\@esphack
	}{
		% This works as intended
		\protected@write\@auxout{}{\string\newlabel{#1}{{#2}{\thepage}}}%
	}
}


% Starred sections are not numbered.
\newcounter{section_counter}
\NewDocumentCommand{\section}{ s m d<> }{
	\par
	\IfBooleanF{#1}{\stepcounter{section_counter}}
	\vspace{4mm}
	\IfBooleanTF{#1}{%
		{\bf\Large \hfill \IfNoValueTF{#2}{Unnamed Section}{#2} \hfill\null}%
	}{%
		{\bf\Large \hfill Part \arabic{section_counter}\IfNoValueF{#2}{: #2} \hfill\null}%
		\IfNoValueF{#3}{\@customlabel{#3}{Part \arabic{section_counter}}}%
	} \\*
	\vspace{2mm}
}

% Generic object.
% Same format as \problem, \theorem, etc, but has no counter.
\NewDocumentCommand{\generic}{ m d<> }{
	\par
	\vspace{3mm}
	{\bf\normalsize #1} \\*
	\IfNoValueF{#2}{\@customlabel{#2}{#1}}
}

% Make a new section type.
% Args: command, counter, title.
\newcommand\@newobj[3]{
	\NewDocumentCommand{#1}{ m d<> }{
		\stepcounter{#2}
		\generic{#3 \arabic{#2}:\IfNoValueF{##1}{ ##1}}
		\IfNoValueF{##2}{\@customlabel{##2}{#3 \arabic{#2}}}
		\IfNoValueF{##2}{\@customlabel{num:##2}{\arabic{#2}}}
	}
}

\if@singlenumbering
	\newcounter{object_counter}
	\def\@problemcounter{object_counter}

	\@newobj{\definition}{object_counter}{Definition}
	\@newobj{\theorem}{object_counter}{Theorem}
	\@newobj{\proposition}{object_counter}{Proposition}
	\@newobj{\example}{object_counter}{Example}
	\@newobj{\remark}{object_counter}{Remark}
\else
	\newcounter{problem_counter}
	\newcounter{theorem_counter}
	\newcounter{definition_counter}
	\newcounter{example_counter}
	\newcounter{proposition_counter}
	\newcounter{remark_counter}
	\def\@problemcounter{problem_counter}

	\@newobj{\definition}{definition_counter}{Definition}
	\@newobj{\theorem}{theorem_counter}{Theorem}
	\@newobj{\proposition}{proposition_counter}{Proposition}
	\@newobj{\example}{example_counter}{Example}
	\@newobj{\remark}{remark_counter}{Remark}
\fi

% These must be defined manually, since
% problems and problemparts use two counters.
\newcounter{problempartcounter}
\NewDocumentCommand{\problem}{ m d<> }{
	\setcounter{problempartcounter}{0}
	\stepcounter{\@problemcounter}
	\generic{Problem \arabic{\@problemcounter}:\IfNoValueF{#1}{ #1}}
	\IfNoValueF{#2}{\@customlabel{num:#2}{\arabic{\@problemcounter}}}
	\IfNoValueF{#2}{\@customlabel{#2}{Problem \arabic{\@problemcounter}}}
}
\NewDocumentCommand{\problempart}{ m d<> }{
	\stepcounter{problempartcounter}
	\generic{Part \arabic{problempartcounter}:\IfNoValueF{#1}{ #1}}
	\IfNoValueF{#2}{\@customlabel{num:#2}{\arabic{problempartcounter}}}
	\IfNoValueF{#2}{\@customlabel{#2}{Problem \arabic{\@problemcounter}.\arabic{problempartcounter}}}
}








% ---------------- %
% Box environments %
% ---------------- %

% Keep track of the current background color.
% Useful for transparent tikz drawings.
\def\ORMCbgcolor{white}

% Make a box environment.
% These can safely be nested.
% Args: title, back color, frame color.
\newenvironment{ORMCbox}[3]{
	% \linehack draws a line across a tcolorbox.
	% tcolorbox only supports two sections, but
	% this hack allows us to have more.
	\def\linehack{
		\begin{tikzpicture}
			\path[use as bounding box]
				(0, 0) --
				(\linewidth, 0);

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

	% Keep track of the current background color.
	% Useful for transparent tikz drawings.
	\def\ORMCbgcolor{#2}

	\begin{tcolorbox}[
		enhanced,
		breakable,
		colback=#2,
		colframe=#3,
		colbacktitle=#3,
		titlerule=0.6mm,
		title={\textbf{#1}},
		title after break={\textbf{#1 (continued)}},
		frame style={draw=none,fill=none},
		boxrule=0mm, % We need this even with hidden borders for correct spacing
		arc=0mm,
		outer arc=0mm
	]
	\raggedright
} {
	\end{tcolorbox}
}

\newenvironment{examplesolution}{
	\begin{ORMCbox}{Example Solution}{black!10!white}{black!65!white}
} {
	\end{ORMCbox}
}

\if@solutions
	\newenvironment{solution}{
		\begin{ORMCbox}{Solution}{ored!10!white}{ored}
	} {
		\end{ORMCbox}
	}
	\newenvironment{instructornote}{
		\begin{ORMCbox}{Note for Instructors}{ocyan!10!white}{ocyan}
	} {
		\end{ORMCbox}
	}
\else
	\excludecomment{solution}
	\excludecomment{instructornote}
\fi








% -------------------- %
% Misc helper commands %
% -------------------- %

% Inline note
\NewDocumentCommand{\ilnote}{ +m }{\begingroup\color{gray}#1\endgroup}

\NewDocumentCommand{\note}{ d[] +m }{
	\IfNoValueTF{#1}{\ilnote{#2}}{\ilnote{\textit{#1:} #2}}\par
}
\long\def\hint#1{\note[Hint]{#1}}
