%
% 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.
%

\ProvidesFile{datemultical-base.def}
[2026/09/17 v0.1.0 Storage for named date data]

\ExplSyntaxOn

% =================================================
% Storage
% =================================================

% RD = JDN - 1721425
% JDN = RD + 1721425
\int_const:Nn \c_dmc_rd_to_jdn_int { 1721425 }

% Common storage
\prop_new:N \g_dmc_rd_prop
\prop_new:N \g_dmc_jdn_prop
\prop_new:N \g_dmc_weekday_prop

% Modern storage
\prop_new:N \g_dmc_date_prop

% Native storage
\prop_new:N \g_dmc_gr_year_prop
\prop_new:N \g_dmc_gr_month_prop
\prop_new:N \g_dmc_gr_day_prop

\prop_new:N \g_dmc_sh_year_prop
\prop_new:N \g_dmc_sh_month_prop
\prop_new:N \g_dmc_sh_day_prop

\prop_new:N \g_dmc_lh_year_prop
\prop_new:N \g_dmc_lh_month_prop
\prop_new:N \g_dmc_lh_day_prop

% =================================================
% Lua result receiver
% =================================================

\cs_new_protected:Npn \dmcLuaStoreDynamic #1#2#3#4
{
  \bool_if:NF \g_dmc_native_bool
  {
    \prop_gput:Nnn
    \g_dmc_date_prop
    { #1 / #2 / #3 }
    { #4 }
  }
}

\cs_new_protected:Npn \dmcLuaStore #1#2#3#4#5
{
  \bool_if:NF \g_dmc_native_bool
  {
    \prop_gput:Nnn
    \g_dmc_date_prop
    { #1 / #2 / year }
    { #3 }

    \prop_gput:Nnn
    \g_dmc_date_prop
    { #1 / #2 / month }
    { #4 }

    \prop_gput:Nnn
    \g_dmc_date_prop
    { #1 / #2 / day }
    { #5 }
  }
}

\cs_new_protected:Npn \dmcLuaStoreRD #1#2
{
  \prop_gput:Nnn
  \g_dmc_rd_prop
  { #1 }
  { #2 }
}

\cs_new_protected:Npn \dmcLuaStoreJDN #1#2
{
  \prop_gput:Nnn
  \g_dmc_jdn_prop
  { #1 }
  { #2 }
}

\cs_new_protected:Npn \dmcLuaStoreWeekday #1#2
{
  \prop_gput:Nnn
  \g_dmc_weekday_prop
  { #1 }
  { #2 }
}

% =================================================
% Set date
% =================================================

\cs_new_protected:Npn \dmc_set:nnnnn #1#2#3#4#5
{
  \bool_if:NTF \g_dmc_native_bool
  {
    % -----------------------------------------
    % Native backend
    % -----------------------------------------

    % First calculate and store JDN.
    \prop_gput:Nnx
    \g_dmc_jdn_prop
    { #2 }
    {
      \dmc_date_to_jdn:nnnn
      { #1 }
      { #3 }
      { #4 }
      { #5 }
    }

    % Then calculate and store RD.
    %
    % The value stored in g_dmc_jdn_prop is expanded first;
    % RD = JDN - 1721425.
    \prop_gput:Nnx
    \g_dmc_rd_prop
    { #2 }
    {
      \int_eval:n
      {
        \prop_item:Nn
        \g_dmc_jdn_prop
        { #2 }
        - \c_dmc_rd_to_jdn_int
      }
    }
  }
  {
    % -----------------------------------------
    % Modern Lua backend
    % -----------------------------------------

    \directlua{
      dmc.set_date(
      "\luaescapestring{#1}",
      "\luaescapestring{#2}",
      "\luaescapestring{#3}",
      "\luaescapestring{#4}",
      "\luaescapestring{#5}"
      )
    }
  }
}

% =================================================
% Get date part
% =================================================

\cs_new:Npn \dmc_get:nnn #1#2#3
{
  \bool_if:NTF \g_dmc_native_bool
  {
    % -----------------------------------------
    % Native backend
    % -----------------------------------------

    \str_case:nnF { #3 }
    {
      { year }
      {
        \dmc_jdn_to_year:nn
        { #1 }
        {
          \prop_item:Nn
          \g_dmc_jdn_prop
          { #2 }
        }
      }

      { month }
      {
        \dmc_jdn_to_month:nn
        { #1 }
        {
          \prop_item:Nn
          \g_dmc_jdn_prop
          { #2 }
        }
      }

      { day }
      {
        \dmc_jdn_to_day:nn
        { #1 }
        {
          \prop_item:Nn
          \g_dmc_jdn_prop
          { #2 }
        }
      }

      { rd }
      {
        \prop_item:Nn
        \g_dmc_rd_prop
        { #2 }
      }

      { jdn }
      {
        \prop_item:Nn
        \g_dmc_jdn_prop
        { #2 }
      }

      { weekday }
      {
        \dmc_jdn_to_weekday:n
        {
          \prop_item:Nn
          \g_dmc_jdn_prop
          { #2 }
        }
      }
    }
    { }
  }
  {
    % -----------------------------------------
    % Modern Lua backend
    % -----------------------------------------

    \str_case:nnF { #3 }
    {
      { year }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / year }
      }

      { month }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / month }
      }

      { day }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / day }
      }

      { rd }
      {
        \prop_item:Nn
        \g_dmc_rd_prop
        { #2 }
      }

      { jdn }
      {
        \prop_item:Nn
        \g_dmc_jdn_prop
        { #2 }
      }

      { weekday }
      {
        \prop_item:Nn
        \g_dmc_weekday_prop
        { #2 }
      }

      { week }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / week }
      }

      { leap }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / leap }
      }

      { leap_month }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / leap_month }
      }

      { leap_day }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / leap_day }
      }

      { major }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / major }
      }

      { cycle }
      {
        \prop_item:Nn
        \g_dmc_date_prop
        { #1 / #2 / cycle }
      }

    }
    { }
  }
}


% =================================================
% Public commands
% =================================================

\NewDocumentCommand \dmcset { O{gr} m m m m }
{
  \dmc_set:nnnnn
  { #1 }
  { #2 }
  { #3 }
  { #4 }
  { #5 }
}

\NewExpandableDocumentCommand \dmcget { O{gr} m m }
{
  \dmc_get:nnn
  { #1 }
  { #2 }
  { #3 }
}


% ---------------------------------
% Variables for \dmcnew key parsing
% ---------------------------------

\tl_new:N \l__dmc_new_year_tl
\tl_new:N \l__dmc_new_month_tl
\tl_new:N \l__dmc_new_day_tl
\tl_new:N \l__dmc_new_cycle_tl
\tl_new:N \l__dmc_new_week_tl
\tl_new:N \l__dmc_new_leap_tl
\tl_new:N \l__dmc_new_leap_month_tl
\tl_new:N \l__dmc_new_leap_day_tl
\tl_new:N \l__dmc_new_major_tl
% \tl_new:N \l__dmc_new_jdn_tl


% ---------------------------------
% Key definitions
% ---------------------------------

\keys_define:nn { dmc / newdate }
{
  year .tl_set:N       = \l__dmc_new_year_tl,
  month .tl_set:N      = \l__dmc_new_month_tl,
  day .tl_set:N        = \l__dmc_new_day_tl,
  cycle .tl_set:N      = \l__dmc_new_cycle_tl,
  week .tl_set:N       = \l__dmc_new_week_tl,
  leap .tl_set:N       = \l__dmc_new_leap_tl,
  leap_month .tl_set:N = \l__dmc_new_leap_month_tl,
  leap_day .tl_set:N   = \l__dmc_new_leap_day_tl,
  major .tl_set:N      = \l__dmc_new_major_tl,
  % jdn .tl_set:N      = \l__dmc_new_jdn_tl,
}

% ---------------------------------
% Clear temporary values
% ---------------------------------

\cs_new_protected:Npn \dmc_new_clear:
{
  \tl_clear:N \l__dmc_new_year_tl
  \tl_clear:N \l__dmc_new_month_tl
  \tl_clear:N \l__dmc_new_day_tl
  \tl_clear:N \l__dmc_new_cycle_tl
  \tl_clear:N \l__dmc_new_week_tl
  \tl_clear:N \l__dmc_new_leap_tl
  \tl_clear:N \l__dmc_new_leap_month_tl
  \tl_clear:N \l__dmc_new_leap_day_tl
  \tl_clear:N \l__dmc_new_major_tl
  % \tl_clear:N \l__dmc_new_jdn_tl
}

% ---------------------------------
% Main implementation of \dmcnew
% ---------------------------------
\cs_new_protected:Npn \dmc_lua_set:nnn #1#2#3
{
  \directlua
  {
    dmc.set_date_kv(
    "\luaescapestring{#1}",
    "\luaescapestring{#2}",
    "\luaescapestring{#3}"
    )
  }
}

\cs_new_protected:Npn \dmc_new:nnn #1#2#3
{
  \bool_if:NTF \g_dmc_native_bool
  {
    % Native backend: use the old interface.
    \dmc_new_clear:
    \keys_set:nn { dmc / newdate } { #3 }

    \dmc_set:nnnnn
    { #1 }
    { #2 }
    { \l__dmc_new_year_tl }
    { \l__dmc_new_month_tl }
    { \l__dmc_new_day_tl }
  }
  {
    % Lua backend: send the complete key-value payload.
    \dmc_lua_set:nnn
    { #1 }
    { #2 }
    { #3 }
  }
}

% ---------------------------------
% Public command
% ---------------------------------

\NewDocumentCommand \dmcnew { O{gr} m m }
{
  \dmc_new:nnn { #1 } { #2 } { #3 }
}

\ExplSyntaxOff

\endinput
