%%%==============================================================================
%% Copyright 2025-present by Alceu Frigeri
%%
%% This work may be distributed and/or modified under the conditions of
%%
%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
%%   version 1.3c (or later), and/or
%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
%%   version 3 (or later)
%%
%% This work has the LPPL maintenance status *maintained*.
%%
%% The Current Maintainer of this work is Alceu Frigeri
%%
%% This is version {1.0} {2025/10/21}
%%
%% The list of files that compose this work can be found in the README.md file at
%% https://ctan.org/pkg/pkginfograb
%%
%%%==============================================================================
\NeedsTeXFormat{LaTeX2e}[2022/06/01]

\ProvidesExplPackage
    {pkginfograb}
    {2025/10/21}
    {1.0}
    {Collecting~ package's~ info~ in~ a~ regular~ way}

%%%%%%%
%%%
%%% Just an attempt of having packages info in a regular way
%%% \pkginfograb_set:nn {<pkg-name>} { props} for each and all.
%%%
%%%%%%%
\cs_new_protected:Npn \pkginfograb_set:nn #1#2
  {
    \prop_new_linked:c {l__pkginfograb_ #1 _prop}
    \prop_set_from_keyval:cn {l__pkginfograb_ #1 _prop}
      { #2 }
  }

%%%%%%%%% 
%%%
%%% self info
%%%
%%%%%%%%%
\pkginfograb_set:nn {pkginfograb}
  { 
    name         = {pkginfograb} ,
    prefix       = {pkginfograb} ,
    date         = {2025/10/21},
    version      = {1.0} ,
    description  = {Collecting~ package's~ info~ in~ a~ regular~ way}
  }
%%%%%%%%% 
%%%%%%%%%

\cs_new_protected:Npn \pkginfograb_get:nn #1#2
  {
    \prop_if_exist:cT { l__pkginfograb_ #1 _prop }
      {
        \prop_item:cn 
          { l__pkginfograb_ #1 _prop } {#2}
      }
  }

\cs_new_protected:Npn \pkginfograb_get:nnN #1#2#3
  {
    \prop_if_exist:cTF { l__pkginfograb_ #1 _prop }
      {
        \prop_get:cnNF { l__pkginfograb_ #1 _prop } { #2 } #3
          { \tl_clear:N #3 }
      }
      { \tl_clear:N #3 }
  }

\cs_new_protected:Npn \pkginfograb_description:n #1
  { 
    \prop_if_exist:cTF { l__pkginfograb_ #1 _prop }
      {
        \par\noindent Package~ \textbf{\pkginfograb_get:nn{#1}{name}}~
        Version:~\pkginfograb_get:nn{#1}{version}~ -~ \pkginfograb_get:nn{#1}{date}
        \par 
        \emph{\pkginfograb_get:nn{#1}{description}}~\par 
      }
      {
        \par \textbf{#1}'s~info~not~defined.\par
      }
  } 


%%%%%%%%%%
%%%%%%%%%% ARGH... below follows version testing...
%%%%%%%%%%


\msg_new:nnnn {pkginfograb} {requires}
  {
    #1~requires~ #2~ version ~ #3~ or~ newer
  }
  {
    Package~#1~ requires~ at~ least~ version ~#3 ~ from ~ package ~ #2.
  }

\msg_new:nnnn {pkginfograb} {version format}
  {
    Invalid~ version~ format:~ #1.~ Should~be~[v]digits[~.~digits[~.~digits]][letters]
  }
  {
    Invalid~ version~ format:~ #1.~ Should~be~[v]digits[~.~digits[~.~digits]][letters]
  }
  
\msg_new:nnnn {pkginfograb} {date format}
  {
    Invalid~ date~ format:~ #1.~ Should~be~YYYY/MM/DD~or~YYYY-MM-DD~or~YYYY.MM.DD
  }
  {
    Invalid~ date~ format:~ #1.~ Should~be~YYYY/MM/DD~or~YYYY-MM-DD~or~YYYY.MM.DD
  }


\tl_new:N \l__pkginfograb_tmpa_tl
\tl_new:N \l__pkginfograb_tmpb_tl
\tl_new:N \l__pkginfograb_tmpc_tl
\tl_new:N \l__pkginfograb_tmpd_tl
\seq_new:N \l__pkginfograb_tmpa_seq
\seq_new:N \l__pkginfograb_tmpb_seq

\cs_new_protected:Npn \pkginfograb_req_version:nnn #1#2#3
  {
    \prop_if_exist:cTF { l__pkginfograb_ #2 _prop }
      {
        \pkginfograb_get:nnN {#2}{version}\l__pkginfograb_tmpa_tl
        
        \__pkginfograb_regex_split:VNTF \l__pkginfograb_tmpa_tl \l__pkginfograb_tmpa_seq
          {
            \__pkginfograb_regex_split:nNTF {#3} \l__pkginfograb_tmpb_seq
              {
                \__pkginfograb_req_version:TF
                  {} % OK, nothing to be done
                  {
                    \msg_error:nnnnn {pkginfograb}{requires}{#1}{#2}{#3}
                  }
              }
              {
                \msg_error:nnn {pkginfograb}{version format}{#3}
              }
          }
          {
            \msg_error:nnV {pkginfograb}{version format} \l__pkginfograb_tmpa_tl
          }            
      }
      {
        \msg_error:nnnnn {pkginfograb}{requires}{#1}{#2}{#3}
      }
  }
  
%%
%% This will match 
%% versionA: [v]{digit]}[letters]
%% versionB: [v]{digit.digit}[letters]
%% versionC: [v]{digit.digit.digit}[letters]
%% so that each regex has 5 capturing groups
%%
%%
\regex_const:Nn \l__pkginfograb_versionA_regex {\A(v?)(\d+)(\d*)(\d*)([a-zA-Z]*)\Z}
\regex_const:Nn \l__pkginfograb_versionB_regex {\A(v?)(\d+)\.(\d+)(\d*)([a-zA-Z]*)\Z}
\regex_const:Nn \l__pkginfograb_versionC_regex {\A(v?)(\d+)\.(\d+)\.(\d+)([a-zA-Z]*)\Z}

\prg_new_protected_conditional:Npnn \__pkginfograb_regex_split:nN #1#2 {TF}
  {
    \regex_split:NnNTF \l__pkginfograb_versionA_regex {#1} #2
      {
        \prg_return_true:
      }
      {
        \regex_split:NnNTF \l__pkginfograb_versionB_regex {#1} #2
          {
            \prg_return_true:
          }
          {
            \regex_split:NnNTF \l__pkginfograb_versionC_regex {#1} #2
              {
                \prg_return_true:
              }
              {
                \prg_return_false:
              }
          }
      }
  }
\prg_generate_conditional_variant:Nnn \__pkginfograb_regex_split:nN  {V} {TF}

\prg_generate_conditional_variant:Nnn \fp_compare:nNn {VNV}{TF}
\prg_generate_conditional_variant:Nnn \str_compare:nNn {VNV}{TF}

\prg_new_protected_conditional:Npnn \__pkginfograb_req_version: {TF}
  {
    \__pkginfograb_build_version:NNN
      \l__pkginfograb_tmpa_seq \l__pkginfograb_tmpc_tl \l__pkginfograb_tmpa_tl
    \__pkginfograb_build_version:NNN 
      \l__pkginfograb_tmpb_seq \l__pkginfograb_tmpd_tl \l__pkginfograb_tmpb_tl
    \fp_compare:VNVTF \l__pkginfograb_tmpc_tl < \l__pkginfograb_tmpd_tl 
      { \prg_return_false: }
      {
        \fp_compare:VNVTF \l__pkginfograb_tmpc_tl = \l__pkginfograb_tmpd_tl
          {
            \str_compare:VNVTF \l__pkginfograb_tmpa_tl < \l__pkginfograb_tmpb_tl
              { \prg_return_false: }
              { \prg_return_true: }
          }
          { \prg_return_true: }
      }
  }

\tl_new:N \l__pkginfograb_tmpx_tl
\cs_new_protected:Npn \__pkginfograb_build_version:NNN #1#2#3
  {
    \seq_pop_left:NN  #1 \l__pkginfograb_tmpx_tl
    \seq_pop_left:NN  #1 \l__pkginfograb_tmpx_tl
    \seq_pop_right:NN #1 \l__pkginfograb_tmpx_tl
    \seq_pop_right:NN #1 #3
    \tl_set:Ne #2 
      { \seq_format:Nn #1 {0>5} }
  }


\prg_new_protected_conditional:Npnn \__pkginfograb_req_date: {TF}
  {
    \__pkginfograb_build_date:NN
      \l__pkginfograb_tmpa_seq \l__pkginfograb_tmpc_tl
    \__pkginfograb_build_date:NN 
      \l__pkginfograb_tmpb_seq \l__pkginfograb_tmpd_tl
    \fp_compare:VNVTF \l__pkginfograb_tmpc_tl < \l__pkginfograb_tmpd_tl 
      { \prg_return_false: }
      { \prg_return_true: }
  }


\cs_new_protected:Npn \__pkginfograb_build_date:NN #1#2
  {
    \seq_pop_left:NN  #1 \l__pkginfograb_tmpx_tl
    \seq_pop_right:NN #1 \l__pkginfograb_tmpx_tl
    \tl_set:Ne #2 
      { \seq_format:Nn #1 {0>2} }
  }


\regex_const:Nn \l__pkginfograb_date_regex {\A(\d\d\d\d)[/\-\.](\d\d?)[/\-\.](\d\d?)\Z}

\cs_new_protected:Npn \pkginfograb_req_date:nnn #1#2#3
  {
    \prop_if_exist:cTF { l__pkginfograb_ #2 _prop }
      {
        \pkginfograb_get:nnN {#2}{date}\l__pkginfograb_tmpa_tl

        \regex_split:NVNTF \l__pkginfograb_date_regex \l__pkginfograb_tmpa_tl \l__pkginfograb_tmpa_seq        
          {
            \regex_split:NnNTF \l__pkginfograb_date_regex {#3} \l__pkginfograb_tmpb_seq        
              {              
                \__pkginfograb_build_date:NN
                  \l__pkginfograb_tmpa_seq \l__pkginfograb_tmpc_tl
                \__pkginfograb_build_date:NN 
                  \l__pkginfograb_tmpb_seq \l__pkginfograb_tmpd_tl
                \fp_compare:VNVTF \l__pkginfograb_tmpc_tl < \l__pkginfograb_tmpd_tl 
                  {
                    \msg_error:nnnnn {pkginfograb}{requires}{#1}{#2}{#3}
                  }
                  {} % OK, nothing to be done
              }
              {
                \msg_error:nnn {pkginfograb}{date format}{#3}
              }
          }
          {
            \msg_error:nnV {pkginfograb}{date format} \l__pkginfograb_tmpa_tl
          }            
      }
      {
        \msg_error:nnnnn {pkginfograb}{requires}{#1}{#2}{#3}
      }
  }



%% just in case one wishes to use this in a LaTeX2e context.  
\cs_new_protected:Npn \pkginfograb_set_aliases:
  {
    \cs_set_eq:NN \PkgInfoSet         \pkginfograb_set:nn
    \cs_set_eq:NN \PkgInfo            \pkginfograb_get:nn
    \cs_set_eq:NN \PkgInfoGet         \pkginfograb_get:nnN
    \cs_set_eq:NN \PkgInfoDescription \pkginfograb_description:n
    \cs_set_eq:NN \PkgInfoReqVersion  \pkginfograb_req_version:nnn
    \cs_set_eq:NN \PkgInfoReqDate     \pkginfograb_req_date:nnn
  }
  
\cs_new_eq:NN \PkgInfoSetAliases \pkginfograb_set_aliases:
