% --------------------------------------------------------------------------
%
% the CHEMMACROS package -- module: `chemformula'
%
% --------------------------------------------------------------------------
% Clemens Niederberger
% --------------------------------------------------------------------------
% https://github.org/cgnieder/chemmacros/
% contact@mychemistry.eu
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
% Copyright 2011--2020 Clemens Niederberger
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2008/05/04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Clemens Niederberger.
% --------------------------------------------------------------------------
\ChemModule{chemformula}{2020/02/02 integration of chemical formulas}

\RequirePackage{amstext}
\chemmacros_load_module:n {charges}

\msg_new:nnn {chemmacros} {unknown-formula-method}
  {
    You~ chose~ the~ formula~ method~ `#1'~ which~ is~ not~ available.~
    I'm~ falling~ back~ to~ `chemformula'~ now.
  }

\msg_new:nnn {chemmacros} {default-formula-method}
  {
    You~ haven't~ chosen~ a~ formula~ method~ so~ I'm~ assuming~ the~ default~
    method~ `chemformula'.
  }

\msg_new:nnn {chemmacros} {formula-conflict}
  {
    You~ have~ loaded~ multiple~ formula~ method~ packages~ but~ haven't~
    chosen~ which~ method~ to~ use!~ I~ will~ use~ `chemformula'. \\
    You~ should~ decide~ for~ only~ one~ of~ the~ packages~ for~ having~ a~
    consistent~ layout.
  }

% --------------------------------------------------------------------------
% generic functions for usage in other packages; those are to be set in each
% method setup:  
\cs_new_protected:Npn \chemmacros_reaction:n #1    {#1}
\cs_new_protected:Npn \chemmacros_chemformula:n #1 {#1}
\cs_generate_variant:Nn \chemmacros_chemformula:n { x,V }

\cs_new_protected:Npn \chemmacros@formula #1  { \chemmacros_chemformula:n {#1} }
\cs_new_protected:Npn \chemmacros@reaction #1 { \chemmacros_reaction:n {#1} }

% --------------------------------------------------------------------------
% setup, check and define each method:
\bool_new:N \l__chemmacros_formula_method_set_bool

\tl_new:N \g_chemmacros_formula_method_tl
\tl_gset:Nn \g_chemmacros_formula_method_tl {chemformula}

\prop_new:N \l__chemmacros_method_packages_prop
    
% #1: package/method name
% #2: preparations
\cs_new_protected:Npn \chemmacros_add_method_package:nn #1#2
  { \prop_put:Nnn \l__chemmacros_method_packages_prop {#1} {#2} }

\cs_new_protected:Npn \chemmacros_setup_method_package:n #1
  {
    \prop_item:Nn \l__chemmacros_method_packages_prop {#1}
    \tl_gset:Nn \g_chemmacros_formula_method_tl {#1}
  }

\prg_new_conditional:Npnn \chemmacros_if_method_package:n #1 {p,T,F,TF}
  {
    \prop_if_in:NnTF \l__chemmacros_method_packages_prop {#1}
      { \prg_return_true: }
      { \prg_return_false: }
  }

\cs_new_protected:Npn \chemmacros_check_formula_method:
  {
    \bool_if:NF \l__chemmacros_formula_method_set_bool
      {
        \bool_set_false:N \l__chemmacros_tmpa_bool
        \prop_map_inline:Nn \l__chemmacros_method_packages_prop
          {
            \chemmacros_if_package_loaded:nT {##1}
              {
                \bool_if:NTF \l__chemmacros_tmpa_bool
                  {
                    \msg_warning:nn {chemmacros} {formula-conflict}
                    \chemmacros_set_formula_method:n {chemformula}
                  }
                  { \chemmacros_set_formula_method:n {##1} }
                \bool_set_true:N \l__chemmacros_tmpa_bool
              }
            }
        \bool_if:NF \l__chemmacros_tmpa_bool
          {
            \msg_info:nn {chemmacros} {default-formula-method}
            \chemmacros_set_formula_method:n {chemformula}
          }
      }
  }

\cs_new_protected:Npn \chemmacros_set_formula_method:n #1
  {
    \chemmacros_if_method_package:nTF {#1}
      { \chemmacros_setup_method_package:n {#1} }
      {
        \msg_warning:nnn {chemmacros} {unknown-formula-method} {#1}
        \chemmacros_setup_method_package:n {chemformula}
      }
    \bool_set_true:N \l__chemmacros_formula_method_set_bool
  }
\cs_generate_variant:Nn \chemmacros_set_formula_method:n {V}

% --------------------------------------------------------------------------
% add formula methods:
\chemmacros_add_method_package:nn {chemformula}
  {
    \chemmacros_integrate_package:nnn {} {chemformula} {2015/09/08}
    \cs_set_protected:Npn \chemmacros_chemformula:n #1
      { \chemformula_chcpd:nn {} {#1} }
    \cs_set_protected:Npn \chemmacros_reaction:n #1
      { \chemformula_ch:nn {} {#1} }
  }
  
\chemmacros_add_method_package:nn {mhchem}
  {
    \chemmacros_integrate_package:nnn {version=4} {mhchem} {}
    \cs_set_protected:Npn \chemmacros_chemformula:n #1 { \ce {#1} }
    \cs_set_protected:Npn \chemmacros_reaction:n #1    { \ce {#1} }
    \chemmacros_after_module:nn {charges}
      {
        \cs_set_protected:Npn \chemmacros_elpair:n #1 { \ce{#1} : }
        \cs_set_protected:Npn \chemmacros_plus:  { + }
        \cs_set_protected:Npn \chemmacros_minus: { - }
        \cs_set_protected:Npn \chemmacros_formal_plus:  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \chemmacros_formal_minus: { \ensuremath{\ominus} }
        \cs_set_protected:Npn \fplus  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \fminus { \ensuremath{\ominus} }
      }
  }

\ChemCompatibilityFrom{5.6}
\chemmacros_add_method_package:nn {chemist}
  {
    \RequirePackage {chemist}
    \cs_set_protected:Npn \chemmacros_chemformula:n #1
      { \chemmacros_text:n { \ChemForm {#1} } }
    \cs_set_protected:Npn \chemmacros_reaction:n #1
      { \chemmacros_text:n { \ChemForm {#1} } }
    \chemmacros_after_module:nn {charges}
      {
        \cs_set_protected:Npn \chemmacros_elpair:n #1
          { \chemmacros_text:n { \ChemForm {#1} : } }
        \cs_set_protected:Npn \chemmacros_plus:  { + }
        \cs_set_protected:Npn \chemmacros_minus: { - }
        \cs_set_protected:Npn \chemmacros_formal_plus:  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \chemmacros_formal_minus: { \ensuremath{\ominus} }
        \cs_set_protected:Npn \fplus  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \fminus { \ensuremath{\ominus} }
      }
  }

\chemmacros_add_method_package:nn {chemfig}
  {
    \RequirePackage {chemfig}
    \cs_set_protected:Npn \chemmacros_chemformula:n #1
      { \printatom {#1} }
    \cs_set_protected:Npn \chemmacros_reaction:n #1
      { \printatom {#1} }
    \chemmacros_after_module:nn {charges}
      {
        \cs_set_protected:Npn \chemmacros_elpair:n #1
          { \Lewis { 0: , \printatom {#1} } }
        \cs_set_protected:Npn \chemmacros_plus:  { + }
        \cs_set_protected:Npn \chemmacros_minus: { - }
        \cs_set_protected:Npn \chemmacros_formal_plus:  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \chemmacros_formal_minus: { \ensuremath{\ominus} }
        \cs_set_protected:Npn \fplus  { \ensuremath{\oplus} }
        \cs_set_protected:Npn \fminus { \ensuremath{\ominus} }
      }
  }
\EndChemCompatibility

% --------------------------------------------------------------------------
\ChemCompatibilityTo{5.1}
\chemmacros_set_formula_method:n {chemformula}
\EndChemCompatibility

\ChemCompatibilityFrom{5.1}
\chemmacros_define_global_keys:n
  { formula .code:n = \chemmacros_set_formula_method:n {#1} }
\EndChemCompatibility

\def\bla{bla}

\AtEndPreamble
  {
    \bool_if:NF \l__chemmacros_formula_method_set_bool
      {
        \bool_lazy_and:nnTF
          { \chemmacros_if_compatibility_p:nn {>=} {5.2} }
          { \chemmacros_if_compatibility_p:nn {<} {5.6} }
          { \chemmacros_check_formula_method: }
          {
            \chemmacros_if_compatibility:nnTF {>=} {5.6}
              { \msg_info:nn {chemmacros} {default-formula-method} }
              { \msg_warning:nn {chemmacros} {default-formula-method} }
            \chemmacros_set_formula_method:n {chemformula}
          }
      }
  }

% --------------------------------------------------------------------------
\file_input_stop:

2015/09/22 - new general option `method' which allows a choice between
             `chemformula' and `mhchem'
2015/10/13 - add missing compatibility definitions
           - check for `mhchem' and `chemformula' and set method accordingly
             if possible
2016/04/27 - further generalization of the `method' concept, new methods
             `chemist' and `chemfig'
           - don't automatically load an available method: load `chemformula'
             if the users haven't decided for themselves and issue a warning
2016/05/03 - correct wrong method check
2020/02/02 - lazy boolean evaluation
2020/02/29 - use \ch even for simple formulas – resolves issue #28
2020/03/02 - undo last change: this makes problems with oxidation numbers in a
             reaction
