% datemultical-format.def
%
% datemultical: Named dates with multi-calendar formatting for LaTeX.
%
% Copyright (C) 2026 Amer Amikhteh
%
% This file is part of the datemultical package.
%
% This work is free software: you may redistribute it and/or modify
% it under the terms of the LaTeX Project Public License as published
% by the LaTeX Project, either version 1.3c of the License, or
% (at your option) any later version.
%
% This work 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.
%
% The full license text is available at:
% https://www.latex-project.org/lppl/
%
% This work is "maintained" by Amer Amikhteh.
%
% The current maintainer of this work is Amer Amikhteh.


\NeedsTeXFormat{LaTeX2e}

\ProvidesFile{datemultical-format.def}
[2026/09/17 v0.1.0 Multi-calendar date formatting]


\ExplSyntaxOn
\makeatletter


% =================================================
% Temporary variables
% =================================================

\tl_new:N \l_dmc_format_tl
\tl_new:N \l_dmc_style_tl
\tl_new:N \l_dmc_calendar_tl

\cs_new_protected:Npn \dmc_style_store:nnn #1 #2 #3
{
    \tl_set:Nx \l_dmc_calendar_tl { \tl_to_str:n {#1} }
    \cs_gset:cpn
    { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl }
    {#3}
}

\cs_new_protected:Npn \dmc_style_fetch:nnN #1 #2 #3
{
    \tl_set:Nx \l_dmc_calendar_tl { \tl_to_str:n {#1} }
    \cs_if_exist:cTF
    { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl }
    {
        \tl_set:Nx #3
        {
            \use:c
            { g_dmc_style_ \l_dmc_calendar_tl _ \tl_to_str:n {#2} _tl }
        }
    }
    {
        \tl_clear:N #3
    }
}


% =================================================
% Calendar-dependent month captions
% =================================================

\cs_new:Npn \dmc_format_month_name:nn #1 #2
{
    \str_case:nnF {#1}
    {
        {gr}
        {
            \dmc_month_name_gr:n {#2}
        }
        {sh}
        {
            \dmc_month_name_sh:n {#2}
        }
        {lh}
        {
            \dmc_month_name_lh:n {#2}
        }
    }
    {}
}

\cs_new:Npn \dmc_format_month_persian:nn #1 #2
{
    \str_case:nnF {#1}
    {
        {gr}
        {
            \dmc_month_name_gr_persian:n {#2}
        }
        {sh}
        {
            \dmc_month_name_sh_persian:n {#2}
        }
        {lh}
        {
            \dmc_month_name_lh_persian:n {#2}
        }
    }
    {}
}

\cs_new:Npn \dmc_format_month_abbrev:nn #1 #2
{
    \str_case:nnF {#1}
    {
        {gr}
        {
            \dmc_month_abbrev_gr:n {#2}
        }
        {sh}
        {
            \dmc_month_abbrev_sh:n {#2}
        }
        {lh}
        {
            \dmc_month_abbrev_lh:n {#2}
        }
    }
    {}
}

% =================================================
% Multi-digit formatting
% =================================================

\cs_new:Npn \dmc_format_two_digits:n #1
{
    \int_compare:nNnTF {#1} < {10}
        {
            0#1
        }
        {
            #1
        }
}

\cs_new:Npn \dmc_format_four_digits:n #1
{
    \int_compare:nNnTF {#1} < {10}
        {
            000#1
        }
        {
            \int_compare:nNnTF {#1} < {100}
                {
                    00#1
                }
                {
                    \int_compare:nNnTF {#1} < {1000}
                        {
                            0#1
                        }
                        {
                            #1
                        }
                }
        }
}


% =================================================
% Bool to intiger
% =================================================

\cs_new:Npn \dmc_format_bool_to_int:n #1
{
    \exp_args:Nx \str_case:nnF {#1}
    {
        {true}  {1}
        {false} {0}
    }
    {#1}
}


% =================================================
% Internal formatting command
% =================================================

\cs_new_protected:Npn \dmc_format_replace_one:nnnnn #1 #2 #3 #4 #5
{
    \tl_replace_all:Nnn
    \l_dmc_format_tl
    {#3}
    {
        \tl_if_blank:nTF {#5}
        {
            \dmcget [#1] {#2} {#4}
        }
        {
            #5
            {
                \dmcget [#1] {#2} {#4}
            }
        }
    }
}

\cs_new_protected:Npn \dmc_format_replace_two:nnnnn #1 #2 #3 #4 #5
{
    \tl_replace_all:Nnn
    \l_dmc_format_tl
    {#3}
    {
        \tl_if_blank:nTF {#5}
        {
            \dmcget [#1] {#2} {#4}
        }
        {
            #5
            {#1}
            {
                \dmcget [#1] {#2} {#4}
            }
        }
    }
}

\cs_new_protected:Npn \dmc_format:nnn #1 #2 #3
{
    \group_begin:

    \tl_set:Nn
    \l_dmc_format_tl
    { #3 }

    % =================================================
    % Year
    % =================================================

    \dmc_format_replace_one:nnnnn {#1} {#2} {yyyy} {year} {\dmc_format_four_digits:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {yy} {year} {\dmc_format_two_digits:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {y} {year} {}

    % =================================================
    % Leap
    % =================================================

    \dmc_format_replace_one:nnnnn {#1} {#2} {lmi} {leap_month} {\dmc_format_bool_to_int:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {ldi} {leap_day} {\dmc_format_bool_to_int:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {li}  {leap} {\dmc_format_bool_to_int:n}

    \dmc_format_replace_one:nnnnn {#1} {#2} {lm} {leap_month} {}
    \dmc_format_replace_one:nnnnn {#1} {#2} {ld} {leap_day} {}
    \dmc_format_replace_one:nnnnn {#1} {#2} {l}  {leap} {}

    % =================================================
    % Month
    % =================================================

    \ifdmc@persian
        \dmc_format_replace_two:nnnnn {#1} {#2} {MMMMP} {month} {\dmc_format_month_persian:nn}
    \fi

    \dmc_format_replace_two:nnnnn {#1} {#2} {MMMM} {month} {\dmc_format_month_name:nn}
    \dmc_format_replace_two:nnnnn {#1} {#2} {MMM} {month} {\dmc_format_month_abbrev:nn}
    \dmc_format_replace_one:nnnnn {#1} {#2} {MM} {month} {\dmc_format_two_digits:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {M} {month} {}

    % =================================================
    % Day
    % =================================================

    \dmc_format_replace_one:nnnnn {#1} {#2} {dd} {day} {\dmc_format_two_digits:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {d} {day} {}

    % =================================================
    % Week
    % =================================================

    \dmc_format_replace_one:nnnnn {#1} {#2} {ww} {week} {\dmc_format_two_digits:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {w} {week} {}

    % =================================================
    % Weekday
    % =================================================

    \ifdmc@persian
        \dmc_format_replace_one:nnnnn {#1} {#2} {EEEEP} {weekday} {\dmc_weekday_persian:n}
    \fi

    \dmc_format_replace_one:nnnnn {#1} {#2} {u} {weekday} {}
    \dmc_format_replace_one:nnnnn {#1} {#2} {EEEE} {weekday} {\dmc_weekday_name:n}
    \dmc_format_replace_one:nnnnn {#1} {#2} {EEE} {weekday} {\dmc_weekday_abbrev:n}

    % =================================================
    % Major and cycle
    % =================================================

    \dmc_format_replace_one:nnnnn {#1} {#2} {R} {major} {}
    \dmc_format_replace_one:nnnnn {#1} {#2} {U} {cycle} {}

    % =================================================
    % Output
    % =================================================

    \tl_use:N
    \l_dmc_format_tl

    \group_end:
}


% =================================================
% Public formatting command
% =================================================

\NewDocumentCommand \dmcformat { O{gr} m m }
{
    \dmc_format:nnn
    {#1}
    {#2}
    {#3}
}


% =================================================
% Internal style setter
% =================================================

\cs_new_protected:Npn \dmc_style_set:nnn #1 #2 #3
{
    \clist_map_inline:nn {#1}
    {
        \dmc_style_store:nnn
        {##1}
        {#2}
        {#3}
    }
}

\NewDocumentCommand \dmcstyle { O{gr} m m }
{
    \dmc_style_set:nnn
    {#1}
    {#2}
    {#3}
}

% =================================================
% Resolve for style
% =================================================

\cs_new_protected:Npn \dmc_style_resolve:nnN #1 #2 #3
{
    \dmc_style_fetch:nnN {#1} {#2} #3

    \tl_if_blank:VTF #3
    {
        \dmc_style_fetch:nnN {gr} {#2} #3
    }
    { }
}

% =================================================
% Public styled-date command
% =================================================

\NewDocumentCommand \dmc { O{gr} m m }
{
    \dmc_style_resolve:nnN
    {#1}
    {#3}
    \l_dmc_style_tl

    \tl_if_blank:VTF \l_dmc_style_tl
    {
        \PackageError{datemultical}
        {Unknown date style '#3' for calendar '#1'}
        {The requested date style has not been defined for this calendar,
            and no Gregorian fallback style exists.}
    }
    {
        \exp_args:NnnV
        \dmc_format:nnn
        {#1}
        {#2}
        \l_dmc_style_tl
    }
}

% =================================================
% Standard date styles
% =================================================

\dmcstyle{full}{EEEE,~MMMM~d,~y}
\dmcstyle{long}{MMMM~d,~y}
\dmcstyle{medium}{MMM~d,~y}
\dmcstyle{short}{yy/MM/dd}

\dmcstyle{short-use}{M/d/yy}
\dmcstyle{ISO}{yyMMdd}
\dmcstyle{ISOext}{yy-MM-dd}
\dmcstyle{american}{MMMM~dd,~yy}
\dmcstyle{shamerican}{MM/dd/yy}
\dmcstyle{british}{dd~MMMM~yy}
\dmcstyle{shbritish}{dd/MM/yy}
\dmcstyle{shbritishdots}{dd.MM.yy}

% =================================================
% Standard date styles for nonstandard calender
% =================================================

\dmcstyle[iso]{short}{yy/ww/dd}
\dmcstyle[mayan_haab,aztec_xihuitl]{short}{MM/dd}

\dmcstyle[korean,old_hindu_lunar,babylonian]{short}{yy/MM/li/dd}
\dmcstyle[hindu_lunar,hindu_lunar_astronomical,tibetan]{short}{yy/MM/lmi/dd/ldi}
\dmcstyle[bahai,bahai_astronomical]{short}{R/U/yy/MM/dd}
\dmcstyle[chinese,japanese]{short}{U/yy/MM/li/dd}
\dmcstyle[olympiad]{short}{U/yy/MM/dd}


% =================================================
% Persian convenience commands
% =================================================

\NewDocumentCommand \ShortShamsi { m }
{\rl{\dmcformat[sh]{#1}{yy/MM/dd}}}
\NewDocumentCommand \ShortGhamari { m }
{\rl{\dmcformat[lh]{#1}{yy/MM/dd}}}

\NewDocumentCommand \ShortMiladi { m }
{\lr{\dmcformat[gr]{#1}{yy/MM/dd}}}

\NewDocumentCommand \Shamsi { m }
{\rl{\dmcformat[sh]{#1}{d~MMMMP~y}}}
\NewDocumentCommand \Ghamari { m }
{\rl{\dmcformat[lh]{#1}{d~MMMMP~y}}}

\NewDocumentCommand \Miladi { m }
{\lr{\dmcformat[gr]{#1}{MMMM~d,~y}}}

\NewDocumentCommand \FaMiladi { m }
{\rl{\dmcformat[gr]{#1}{d~MMMMP~y}}}

\NewDocumentCommand \Persianweekday { m }
{\rl{\dmcformat{#1}{EEEEP}}}


\makeatother
\ExplSyntaxOff

\endinput