#ifndef C_POSOLOGIEGRAMMAR_H
#define C_POSOLOGIEGRAMMAR_H

#include<QStringList>
//=================== C_PosologieGrammar ===================================
/*! \class C_PosologieGrammar
 *  \brief Class to set and interpret posologie grammar.
 */

class C_PosologieGrammar
{
public:    enum flags  {NOT_LITERAL        = 0,
                        UP_QUANTITE        = 1,
                        UP_JUST_FRACTION   = 2,
                        DURATION           = 4,
                        SEQUENCE_HOUR      = 8,
                        MOMENT_MEAL        = 16,
                        INDICATION_LIST    = 32,
                        INDICATION_CODE    = 64,
                        INDICATION_TYPE    = 128,
                        ALL_LITERAL        = 31
                       };
           enum indicFlag  { CODE       = 0,
                             CODE_TYPE  = 1,
                             LIBELLE    = 2,
                             ALL_INDIC  = 3
                           };


          explicit  C_PosologieGrammar(const QString &grammar_expression="");
          //---------------------------- setGrammar ----------------------------------------------
          /*! \brief set the literal grammar string. if empty a empty skeleton grammar  is set
           *  the grammar string is updated whith flags contents indications
           *  \param const QString &grammar_expression :   grammar string to set
           *  \return the grammar string.
          */
          QString   setGrammar(const QString &grammar_expression);

          //---------------------------- grammar ------------------------------------------------
          /*! \brief return the grammar string
          */
          QString   grammar(){return m_grammar_expression;}

          //---------------------------- setLiteral ------------------------------------------------
          /*! \brief set how the grammar must be converted
           *  \param int must_be_literal (default = C_PosologieGrammar::ALL_LITERAL).
           *   if  must_be_literal is set to  undefined if -1 (the grammar string try to be used for this and if not possible it's defined to C_PosologieGrammar::NOT_LITERAL)
           *         otherwise it's must be a combination of : C_PosologieGrammar::UP_QUANTITE
           *                                                   C_PosologieGrammar::UP_JUST_FRACTION   //  conversion uniquement de 0.25 en un quart 0.5 en un demi 0.75 en trois quart
           *                                                   C_PosologieGrammar::DURATION
           *                                                   C_PosologieGrammar::SEQUENCE_HOUR
           *                                                   C_PosologieGrammar::MOMENT_MEAL
           *                                                   C_PosologieGrammar::INDICATION_LIST   indications list must be showed
           *                                                   C_PosologieGrammar::INDICATION_CODE   indications code must be showed
           *                                                   C_PosologieGrammar::INDICATION_TYPE   indications code typ (CIP CISP etc.) must be showed
           *         this parameter define how numerics values must be converted in literal string.
           */
          void      setLiteralFlag(int must_be_literal = C_PosologieGrammar::ALL_LITERAL);
          //---------------------------- isLiteral ------------------------------------------------
          /*! \brief return if all in this posologie must be converted in literal form
          */
          int       isLiteral();
          //---------------------------- toString ------------------------------------------------
          /*! \brief return human readable string from posologie grammar.
           *      <gph>
           *         <gph_id>301546</gph_id>
           *        <gph_pk>123</gph_pk>
           *         <gph_uf>comprimé</gph_uf>
           *         <gph_voie>orale</gph_voie>
           *         <gph_cm>UP_QUANTITE DURATION</gph_cm>
           *         <gph_in>
           *             <gph_il>I13.1|CIM|insuffisance rénale et cardiopathie hypertensive</gph_il>
           *             <gph_il>P96.0|CIM|insuffisance rénale congénitale</gph_il>
           *         </gph_in>
           *         <gph_co>à prendre avec un grand verre d'eau sans respirer pendant 30 minutes</gph_co>
           *      </gph>
           *      <gps>
           *         <gpp>[1;m|2;M|4;s]/8</gpp>
           *         <gpp>[0.5;m|1;M15r|2;sr30|3;h10-13]/4\</gpp>
           *         <gpp>[0.5;m|1;s]/3</gpp>
           *      </gps>
           *   if  m_must_be_literal is set to  undefined if -1 (the grammar string try to be used for this and if not possible it's defined to C_PosologieGrammar::NOT_LITERAL)
           *         otherwise it's must be a combination of : C_PosologieGrammar::UP_QUANTITE
           *                                                   C_PosologieGrammar::UP_JUST_FRACTION   //  conversion uniquement de 0.25 en un quart 0.5 en un demi 0.75 en trois quart
           *                                                   C_PosologieGrammar::DURATION
           *                                                   C_PosologieGrammar::SEQUENCE_HOUR
           *                                                   C_PosologieGrammar::MOMENT_MEAL
           *                                                   C_PosologieGrammar::INDICATION_LIST   indications list must be showed
           *                                                   C_PosologieGrammar::INDICATION_CODE   indications code must be showed
           *                                                   C_PosologieGrammar::INDICATION_TYPE   indications code typ (CIP CISP etc.) must be showed
           *         this parameter define how numerics values must be converted in literal string.
           *  \param QString &_up_forme      if == "" the grammar string try to be used to define, this parameter is the drug unit form.
           *  \return a french human readable string (for other langs the source code is there after ...)
           */
          QString   toString(const QString &_up_forme  = "" );
          //---------------------------- get_indicationsList  ------------------------------------------------
          /*! \brief return indication list from grammar string
           *  \param const QString &grammar_expression :     grammar input string as
           *  \return list code if present as 'code'|'typCode'|'libelle'
          */
          QStringList get_indicationsList(){return get_indicationsList(m_grammar_expression);}
          //---------------------------- indication  ------------------------------------------------
          /*! \brief return indication from posologie grammar.
           *  \param const QString &grammar_expression :     grammar input string which must be modified
           *  \param , int index :     index of indication to retrieve
           *  \return indication expression 'code'|'typCode'|'libelle'
          */
          QString get_indication(int index, int flag = C_PosologieGrammar::ALL_INDIC){return get_indication(m_grammar_expression, index, flag);}
          //---------------------------- setCip  ------------------------------------------------
          /*! \brief set the cip code in posologie grammar.
           *  \param const QString &cip :     cip code to set
           *  \return modified grammar expression.
          */
          QString setCip(const QString &cip) {return setCip(m_grammar_expression, cip);}
          //---------------------------- cip  ------------------------------------------------
          /*! \brief return the cip code string from posologie grammar. If not present return ""
           *  \param const QString &grammar_expression :     grammar input string
           *  \return cip code if present.
          */
          QString cip (){return cip(m_grammar_expression);}
          //---------------------------- setDrugRoute  ------------------------------------------------
          /*! \brief set the drug route string in posologie grammar.  [static]
          *  \param const QString &grammar_expression :     grammar input string which must be modified
          *  \param const QString &voie :     drug route to set
          *  \return modified grammar expression.
         */
          QString setDrugRoute(const QString &drugRoute){return setDrugRoute(m_grammar_expression, drugRoute);}
         //---------------------------- drugRoute  ------------------------------------------------
         /*! \brief return drug route string from posologie grammar. If not present return "" [static]
          *  \param const QString &grammar_expression :     grammar input string
          *  \return the drug route if present.
          */
          QString drugRoute(){return drugRoute(m_grammar_expression);}
          //---------------------------- setUnitPriseForm  ------------------------------------------------
          /*! \brief set the unit prise form string in posologie grammar.
           *  \param const QString &unitUPForm :     unit prise form to set
           *  \return modified grammar expression.
          */
          QString setUnitPriseForm(const QString &unitUPForm) {return setUnitPriseForm(m_grammar_expression, unitUPForm);}
          //---------------------------- get_indicationsList [static] ------------------------------------------------
          /*! \brief return indication list from grammar string
           *  \param const QString &grammar_expression :     grammar input string as
           *  \return list code if present as 'code'|'typCode'|'libelle'
          */
  static QStringList get_indicationsList(const QString &grammar_expression);
          //---------------------------- get_indication [static] ------------------------------------------------
          /*! \brief return indication from posologie grammar.  [static]
           *  \param const QString &grammar_expression :     grammar input string which must be modified
           *  \param , int index :     index of indication to retrieve
           *  \return indication expression as 'code'|'typCode'|'libelle'
          */
   static QString get_indication(const QString &grammar_expression, int index, int flag = C_PosologieGrammar::ALL_INDIC);
          //---------------------------- literalFlagToString [static] ------------------------------------------------
          /*! \brief return a literal string from int flag.  [static]
           *  \param int must_be_literal :    int flag
           *  \return literal string.
          */
   static QString literalFlagToString(int must_be_literal);
          //---------------------------- literalStringToFlag [static] ------------------------------------------------
          /*! \brief return the literal flag from literal string.  [static]
           *  \param const QString &conv_mod :  literal string to convert in flag
           *  \return literal flag.
           */
   static int literalStringToFlag(const QString &conv_mod);

          //---------------------------- empty_skeleton_grammar [static] ------------------------------------------------
          /*! \brief return a empty grammar string.  [static]
           *  \return empty grammar string.
          */
   static QString empty_skeleton_grammar();

          //---------------------------- setCip [static] ------------------------------------------------
          /*! \brief set cip code in posologie grammar.  [static]
           *  \param const QString &grammar_expression :     grammar input string which must be modified
           *  \param const QString &cip :     cip code to set
           *  \return modified grammar expression.
          */
   static QString setCip(QString &grammar_expression, const QString &cip);

          //---------------------------- cip [static] ------------------------------------------------
          /*! \brief return the cip code string from posologie grammar. If not present return "" [static]
           *  \param const QString &grammar_expression :     grammar input string as
           *  \return cip code if present.
          */
   static QString cip (const QString &grammar_expression);

          //---------------------------- setDrugRoute [static] ------------------------------------------------
          /*! \brief set the drug route string in posologie grammar.  [static]
          *  \param const QString &grammar_expression :     grammar input string which must be modified
          *  \param const QString &drugRoute :    drug route to set
          *  \return modified grammar expression.
         */
   static QString setDrugRoute(QString &grammar_expression, const QString &drugRoute);

         //---------------------------- drugRoute [static] ------------------------------------------------
         /*! \brief return drug route string from posologie grammar. If not present return "" [static]
          *  \param const QString &grammar_expression :     grammar input string
          *  \return the voie if present.
          */
   static QString drugRoute(const QString &grammar_expression);

          //---------------------------- setUnitPriseForm [static] ------------------------------------------------
          /*! \brief set the unit prise form string in posologie grammar.  [static]
           *  \param const QString &grammar_expression :     grammar input string which must be modified
           *  \param const QString &unitUPForm :     unit prise form to set
           *  \return modified grammar expression.
          */
   static QString setUnitPriseForm(QString &grammar_expression, const QString &unitUPForm);

          //---------------------------- unitPriseForm [static] ------------------------------------------------
          /*! \brief return the unit prise form string from posologie grammar. If not present return "" [static]
           *  \param const QString &grammar_expression :     grammar input string as
           *  \return the unit prise form if present.
          */
   static QString unitPriseForm(const QString &grammar_expression);

          //---------------------------- get_cip_pk [static] ------------------------------------------------
          /*! \brief return cip code string from posologie grammar. If not present return "" [static]
           *  \param const QString &grammar_expression :     grammar input string
           *  \param QString *pk :  if not zero pk code will be returned in the contents of this QString pointer.
           *  \return cip code if present.
          */
   static QString get_cip_pk(const QString &grammar_expression, QString *pk  = 0 );

          //---------------------------- toString [static] ------------------------------------------------
          /*! \brief return human readable string from posologie grammar.
          *  \param const QString &grammar_expression     xml grammar input string as
          *      <gph>
          *         <gph_id>301546</gph_id>
          *        <gph_pk>123</gph_pk>
          *         <gph_uf>comprimé</gph_uf>
          *         <gph_cm>UP_QUANTITE DURATION</gph_cm>
          *         <gph_in>
          *             <gph_il>I13.1|CIP|insuffisance rénale et cardiopathie hypertensive</gph_il>
          *            <gph_il>P96.0|CIP|insuffisance rénale congénitale</gph_il>
          *         </gph_in>
          *         <gph_co>à prendre avec un grand verre d'eau sans respirer pendant 30 minutes</gph_co>
          *      </gph>
          *      <gps>
          *         <gpp>[1;m|2;M|4;s]J8</gpp>
          *         <gpp>[0.5;m|1;M15r|2;sr30|3;h10-13]J4\</gpp>
          *         <gpp>[0.5;m|1;s]J3</gpp>
          *      </gps>
          *  \param int must_be_literal  undefined if -1 (the grammar string try to be used for this and if not possible it's defined to C_PosologieGrammar::NOT_LITERAL)
          *         otherwise it's must be a combination of : C_PosologieGrammar::UP_QUANTITE
          *                                                   C_PosologieGrammar::UP_JUST_FRACTION   //  conversion uniquement de 0.25 en un quart 0.5 en un demi 0.75 en trois quart
          *                                                   C_PosologieGrammar::DURATION
          *                                                   C_PosologieGrammar::SEQUENCE_HOUR
          *                                                   C_PosologieGrammar::MOMENT_MEAL
          *                                                   C_PosologieGrammar::INDICATION_LIST   indications list must be showed
          *                                                   C_PosologieGrammar::INDICATION_CODE   indications code must be showed
          *                                                   C_PosologieGrammar::INDICATION_TYPE   indications code typ (CIP CISP etc.) must be showed
          *         this parameter define how numerics values must be converted in literal string.
          *  \param QString &_up_forme      if == "" the grammar string try to be used to define, this parameter is the drug unit form.
          *  \return a french human readable string (for other langs the source code is there after ...)
          */
   static QString   toString(const QString &grammar_expression, const QString &_up_forme,    int must_be_literal  = C_PosologieGrammar::NOT_LITERAL );

private:
   static QString   sequenceToString(const QString &sequence,                                int must_be_literal  = false, const QString &_up_form="");
   static QString   sequence_daysToString(const QString &seq_days,     QString &periodUnit,  int must_be_literal  = false );
   static QString   sequence_timeToString(const QString &seq_time,                           int must_be_literal  = false , const QString &_up_forme="");
   static QString   numberToLiteral( QString number, QString &up_forme , int justOneFraction  = false );
   static QString   numberToLiteral( int number,     char sexe  = 'm' );
   static QString   adjustPlurielUpForme(int nb, const QString &_up_forme, char &sexe);
   static QString   adjustUniteToSexe(const QString &unite, char sexe );
private:
   QString   m_grammar_expression;
   int       m_must_be_literal;
};
#endif // C_POSOLOGIEGRAMMAR_H
