% Kale Ewasiuk (kalekje@gmail.com)
% 2025-02-14
% Copyright (C) 2025 Kale Ewasiuk
%
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the "Software"), to deal
% in the Software without restriction, including without limitation the rights
% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
% copies of the Software, and to permit persons to whom the Software is
% furnished to do so, subject to the following conditions:
%
% The above copyright notice and this permission notice shall be included in
% all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
% ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
% TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
% PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
% SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
% ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
% ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
% OR OTHER DEALINGS IN THE SOFTWARE.

\RequirePackage{luacode}
\RequirePackage{luakeys}
\RequirePackage{penlightplus}


\luadirect{luatbls = require'luatbls'}


\NewDocumentCommand{\tblnew}{m}{\luadirect{% initialize a tbl and set empty
  luatbls[\luastring{#1}] = {}
  luatbls._rec_tbl = \luastring{#1}
}}


\NewDocumentCommand{\tblchg}{ m }{\luadirect{% change recent table
  luatbls._rec_tbl = luatbls._get_tbl_name(\luastring{#1})
}}

\NewDocumentCommand{\tblfrkv}{m +m O{}}{\luadirect{% parse a tbl from key-vals, naked are set to boolean
  luatbls._rec_tbl_opts = luatbls._luakeys.parse(\luastring{#3}, {naked_as_value=true})
  luatbls[\luastring{#1}] = luatbls._luakeys.parse(string.subpar(\luastring{#2}), luatbls._rec_tbl_opts)
  luatbls._rec_tbl = \luastring{#1}
}}

\NewDocumentCommand{\tblfrkvN}{m +m O{}}{\luadirect{%
  luatbls._rec_tbl_opts = luatbls._luakeys.parse(\luastring{#3}, {naked_as_value=true})
  luatbls[\luastring{#1}] = luatbls._luakeys.parse(string.subpar(\luastringN{#2}), luatbls._rec_tbl_opts)
  luatbls._rec_tbl = \luastring{#1}
}}

\NewDocumentCommand{\tblfrcsv}{m +m O{}}{\tblfrkv{#1}{#2}[naked_as_value=true,#3]}% naked are set to array

\NewDocumentCommand{\tblfrcsvN}{m +m O{}}{\tblfrkvN{#1}{#2}[naked_as_value=true,#3]}

\NewDocumentCommand{\tblkvundefcheck}{}{\luadirect{luatbls._check_recent_tbl_undefault()}}% check defaults list and throw error if foreign keys were used

\NewDocumentCommand{\tblenforcechoices}{m m}{\luadirect{luatbls._check_choices(\luastring{#1},\luastring{#2})}}




\NewDocumentCommand{\tblapp}{m m}{\luadirect{% append to a table (ie using integer index)  with a value (second arg)
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  table.insert(luatbls[__tbl__], \luastring{#2})
}}


\NewDocumentCommand{\tblappN}{m m}{\luadirect{% append to a table (ie using integer index)  with a value (second arg) #
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  table.insert(luatbls[__tbl__], \luastringN{#2})
}}


\NewDocumentCommand{\tblcon}{m m}{\luadirect{% concatenate to a table (ie using integer index)  with a  list of comma separated values (second arg) #
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  for k, v in ipairs(luatbls._luakeys.parse(string.subpar(\luastring{#2}), {naked_as_value=true})) do
    table.insert(luatbls[__tbl__], v)
  end
}}


\NewDocumentCommand{\tblconN}{m m}{\luadirect{% concatenate to a table (ie using integer index)  with a  list of comma separated values (second arg) #
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  for k, v in ipairs(luatbls._luakeys.parse(string.subpar(\luastringN{#2}), {naked_as_value=true})) do
    table.insert(luatbls[__tbl__], v)
  end
}}


\NewDocumentCommand{\tbladd}{m m}{\luadirect{% add a kv pair to a table
  __tbl__, __key__ = luatbls._get_tbl_index(\luastring{#1}, true)
  luatbls[__tbl__][__key__] = \luastring{#2}
}}

\NewDocumentCommand{\tbladdN}{m m}{\luadirect{% add a kv pair to a table
  __tbl__, __key__ = luatbls._get_tbl_index(\luastring{#1}, true)
  luatbls[__tbl__][__key__] = \luastringN{#2}
}}


\NewDocumentCommand{\tblupd}{m m}{\luadirect{% update to a table (ie using integer index)  with a  list of comma separated values (second arg) #
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  __tbl_new__ = luatbls._luakeys.parse(string.subpar(\luastring{#2})
  penlight.tablex.update(luatbls[__tbl__], __tbl_new__)
}}


\NewDocumentCommand{\tblupdN}{m m}{\luadirect{% update to a table (ie using integer index)  with a  list of comma separated values (second arg) #
  __tbl__ = luatbls._get_tbl_name(\luastring{#1})
  __tbl_new__ = luatbls._luakeys.parse(string.subpar(\luastringN{#2})
  penlight.tablex.update(luatbls[__tbl__], __tbl_new__)
}}




\NewDocumentCommand{\tblget}{m}{\luadirect{% get an item using i syntax
  luatbls._get_tbl_item(\luastring{#1}, true)
}}

\NewDocumentCommand{\tblgetE}{m}{\luadirect{% get an item explicitly
  tex.sprint(tostring(luatbls.#1))
}}

\NewDocumentCommand{\tblset}{m m}{\luadirect{% set item with {value}
  luatbls._set_tbl_item(\luastring{#1}, \luastring{#2})
}}

\NewDocumentCommand{\tblsetN}{m m}{\luadirect{% set item with {value}
  luatbls._set_tbl_item(\luastring{#1}, \luastringN{#2})
}}

\NewDocumentCommand{\tblsetE}{m m}{\luadirect{luatbls.#1 = #2}}% set item with {value}


\NewDocumentCommand{\tblif}{ m +m +O{}}{\ifluax{luatbls._get_tbl_item(\luastring{#1})}{#2}[#3]}

\NewDocumentCommand{\tblifv}{m +m +O{}}{\ifluaxv{luatbls._get_tbl_item(\luastring{#1})}{#2}[#3]}

\NewDocumentCommand{\tblifeq}{m m +m +O{}}{\ifluax{luatbls._get_tbl_item(\luastring{#1}) == \expanded{#2}}{#3}[#4]}

\NewDocumentCommand{\tblifeqstr}{m m +m +O{}}{\ifluax{luatbls._get_tbl_item(\luastring{#1}) == \luastring{#2}}{#3}[#4]}


\NewDocumentCommand{\tblfor}{  m +m }{\luadirect{luatbls._for_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblforN}{ m +m }{\luadirect{luatbls._for_tbl(\luastring{#1}, \luastringN{#2})}}

\NewDocumentCommand{\tblforE}{  m +m }{\luadirect{luatbls._for_tbl_e(luatbls.#1, \luastring{#2})}}
\NewDocumentCommand{\tblforEN}{ m +m }{\luadirect{luatbls._for_tbl_e(luatbls.#1, \luastringN{#2})}}


\NewDocumentCommand{\tbldef}{  m o }{\luadirect{luatbls._def_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblgdef}{ m o }{\luadirect{luatbls._def_tbl(\luastring{#1}, \luastring{#2}, 'global')}}

\NewDocumentCommand{\tbldefs}{ m o }{\luadirect{luatbls._def_tbl_some(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblgdefs}{ m  o }{\luadirect{luatbls._def_tbl_some(\luastring{#1},  \luastring{#2}, 'global')}}



\ProvideDocumentCommand{\providenewlength}{ m }{\ifdeflength{#1}{}{\newlength{#1}}}

\NewDocumentCommand{\tblmaketoggle}{ m o }{\luadirect{luatbls._make_toggle_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblmakegtoggle}{ m o }{\luadirect{luatbls._make_toggle_tbl(\luastring{#1}, \luastring{#2}, '\\global')}}

\NewDocumentCommand{\tblmaketoggles}{ m o }{\luadirect{luatbls._make_toggles_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblmakegtoggles}{ m o }{\luadirect{luatbls._make_toggles_tbl(\luastring{#1}, \luastring{#2}, '\\global')}}


\NewDocumentCommand{\tblmakelength}{ m o }{\luadirect{luatbls._make_length_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblmakeglength}{ m o }{\luadirect{luatbls._make_length_tbl(\luastring{#1}, \luastring{#2}, '\\global')}}

\NewDocumentCommand{\tblmakelengths}{ m o }{\luadirect{luatbls._make_lengths_tbl(\luastring{#1}, \luastring{#2})}}
\NewDocumentCommand{\tblmakeglengths}{ m o }{\luadirect{luatbls._make_lengths_tbl(\luastring{#1}, \luastring{#2}, '\\global')}}


\NewDocumentCommand{\tbldefxy}{ m o }{\luadirect{luatbls._def_tbl_coords(\luastring{#1}, \luastring{#2})}}% define #2x and #2y from a space delimited x-y pair

\NewDocumentCommand{\tblapply}{m m O{}}{\luadirect{luatbls._apply_tbl(\luastring{#1}, \luastring{#2}, \luastring{#3})}}

\NewDocumentCommand{\tblprt}{s m}{%
  \luadirect{penlight.wrth(luatbls._get_tbl(\luastring{#2}),'luatbls: '..\luastring{#2})}%
  \IfBooleanTF{#1}{\PackageError{luatbls}{Program terminated by tblprt*}{}\stop}{}%
}