#ifndef C_FRM_PRESCRIPTION_H
#define C_FRM_PRESCRIPTION_H

#include "C_BDM_Api.h"
#include <QFrame>
#include <QPointer>
#include <QPushButton>
#include <QLineEdit>
#include <QEvent>
#include <QTextEdit>
#include <QScrollArea>

class QRubberBand;
class QRect;
//====================================== CMyQTextEdit =======================================================
class CMyQTextEdit : public QTextEdit
{
Q_OBJECT
//........................................... METHODES ...........................................................
public:
     CMyQTextEdit (const QString   &text            = "",
                   QWidget*        parent           = 0 ,
                   const char*     name             = 0 ,
                   void*           ptr              = 0
          )
        : QTextEdit (name , parent)
    {   setText(text);
        setObjectName(name);
        m_ptr      = ptr;
    }
     void  mousePressEvent ( QMouseEvent * e );
//........................................... DATA ...............................................................
private:
  void   *m_ptr;
};

//====================================== CMyQLineEdit =======================================================
class CMyQLineEdit : public QLineEdit
{
Q_OBJECT
//........................................... METHODES ...........................................................
public:
     CMyQLineEdit (const QString   &text            = "",
                   QWidget*        parent           = 0 ,
                   const char*     name             = 0 ,
                   void*           ptr              = 0
          )
        : QLineEdit (name , parent)
    {   setText(text);
        setObjectName(name);
        m_ptr      = ptr;
        setFocusPolicy(Qt::StrongFocus);
        setAlignment ( Qt::AlignHCenter );
        connect( this, SIGNAL( returnPressed ()  ),  this , SLOT( Slot_returnPressed() ));

    }

     CMyQLineEdit (const QRect     &rect       ,
                   const QString   &text   = "",
                   QWidget*         parent = 0 ,
                   const QString    &name  = 0 ,
                   void*            ptr    = 0
                  )
         : QLineEdit (name , parent)
    {   setText(text);
        setObjectName(name);
        m_ptr      = ptr;
        setGeometry(rect);
        setFocusPolicy(Qt::StrongFocus);
        setAlignment ( Qt::AlignHCenter );
        connect( this, SIGNAL( returnPressed ()  ),  this , SLOT( Slot_returnPressed() ));
    }
     bool  event           ( QEvent      * e );
     void  focusInEvent    ( QFocusEvent * e );
     void  focusOutEvent   ( QFocusEvent * e );
     void  mousePressEvent ( QMouseEvent * e );
     void  setCaractersMask(const QString &mask);
signals:
     void Sign_returnPressed(const QString &name, CMyQLineEdit *pCMyQLineEdit, void *ptr, Qt::KeyboardModifiers modifiers);
     void Sign_focusIn      (const QString &name, CMyQLineEdit *pCMyQLineEdit, void *ptr);
     void Sign_focusOut     (const QString &name, CMyQLineEdit *pCMyQLineEdit, void *ptr);
public slots:
     void Slot_returnPressed()
     { emit Sign_returnPressed( objectName(), this, m_ptr, 0);
     }

//........................................... DATA ...............................................................
private:
  QString m_caractersMask;
  void   *m_ptr;
};
//====================================== CMyButton =======================================================
class CMyButton : public QPushButton
{
Q_OBJECT
//........................................... METHODES ...........................................................
public:
     CMyButton (QWidget*        parent           = 0,
                const QString   &name            = 0,
                void*           ptr              = 0

          )
        : QPushButton (name , parent)
    {
        setObjectName(name);
        m_ptr  = ptr;
        connect( this, SIGNAL( clicked() ), this, SLOT( Slot_OnButtonClicked() ) );
    }

     CMyButton (const QRect     &rect      ,
                QWidget*         parent = 0,
                const QString    &name  = 0, // "buton text , object name"
                void*            ptr    = 0
           )
         : QPushButton (name , parent)
     {
         setObjectName(name);
         m_ptr  = ptr;
         setGeometry(rect);
         connect( this, SIGNAL( clicked() ), this, SLOT( Slot_OnButtonClicked() ) );
     }
     CMyButton (const QIcon     &icon,
                const QRect     &rect,
                QWidget*         parent           = 0,
                const QString&   name             = 0,
                void*            ptr              = 0
               )
         : QPushButton (icon, name, parent)   // important permet que le widget soit enfant du parent
     {setObjectName(name);
      m_ptr  = ptr;
      setIconSize ( QSize(rect.width(),rect.height()));
      setGeometry(rect);
      connect( this, SIGNAL( clicked() ), this, SLOT( Slot_OnButtonClicked() ) );
     }

     CMyButton (const QIcon    & icon,
                QWidget*         parent           = 0,
                const QString&   name             = 0,
                void*            ptr              = 0
               )
         : QPushButton (icon, name, parent)   // important permet que le widget soit enfant du parent
     {setObjectName(name);
      m_ptr  = ptr;
      setIconSize ( QSize(16,16) );
      connect( this, SIGNAL( clicked() ), this, SLOT( Slot_OnButtonClicked() ) );
     }

//QString getObjectName(){return m_name;}

void setObjectName ( const QString & name )   //-----------
{int pos = name.indexOf(',');
 if (pos != -1)
    {//m_name = name.right(pos+1);
     QPushButton::setObjectName(name.right(pos+1));
     setText(name.left(pos));
    }
 else
    {//m_name = name;
     QPushButton::setObjectName(name);
     setText(name);
    }
}

signals:
 void Sign_ButtonClickedPtr(const QString &name, void *ptr, CMyButton* pCMyButton);
 void Sign_ButtonClickedPtr(const QString &name, void *ptr);
 void Sign_ButtonClicked(   const QString &name);

public slots:
   void Slot_OnButtonClicked()
    {if (m_ptr==0) emit Sign_ButtonClicked   (this->objectName());
     else          emit Sign_ButtonClickedPtr(this->objectName(), m_ptr);
    }

//........................................... DATA ...............................................................
private:
 //QString m_name;
 void   *m_ptr;

};

//====================================== C_BitMapCollection =======================================================
class C_BitMapCollection
 {
 public:
     C_BitMapCollection(const QString & pathImage)
     {m_objectsDel          = QPixmap(pathImage + "objectDel.png");
      m_ButtonMatin         = QPixmap(pathImage + "matin.png");
      m_ButtonMidi          = QPixmap(pathImage + "midi.png");
      m_ButtonApresMidi     = QPixmap(pathImage + "apresmidi.png");
      m_ButtonSoir          = QPixmap(pathImage + "soir.png");
      m_ButtonCoucher       = QPixmap(pathImage + "coucher.png");
      m_ButtonNuit          = QPixmap(pathImage + "nuit.png");
      m_ButtonSequenceList  = QPixmap(pathImage + "deploylist.png");
      m_ButtonSequenceAdd   = QPixmap(pathImage + "sequenceadd.png");
      m_ButtonSequenceDel   = QPixmap(pathImage + "sequencedel.png");
     }
 public:
     QPixmap m_objectsDel;
     QPixmap m_ButtonMatin;
     QPixmap m_ButtonMidi;
     QPixmap m_ButtonApresMidi;
     QPixmap m_ButtonSoir;
     QPixmap m_ButtonCoucher;
     QPixmap m_ButtonNuit;
     QPixmap m_ButtonSequenceList;
     QPixmap m_ButtonSequenceAdd;
     QPixmap m_ButtonSequenceDel;

 };
//====================================== C_Frm_PosologieHitList =======================================================
class C_Frm_PosologieHitList : public QScrollArea, QStringList
{
Q_OBJECT
//........................................... METHODES ...........................................................
public:
    enum direction {
        NEXT     = 0,
        PREVIOUS = -1
    };

     C_Frm_PosologieHitList (const QStringList   &grammarList ,
                             const QRect         &geometry_rect,
                             QWidget*        parent             = 0 ,
                             const char*     name               = 0
                            );
     QWidget *nextEditWidget();
     QWidget *previousEditWidget();
     QWidget *setWidgetEditFocus(QWidget *pQWidgetNew, QWidget *pQWidgetOld);
     void     setWidgetEditFocus(int direction);
     bool     event ( QEvent * ev );
     void     mousePressEvent ( QMouseEvent * event );
     QString  selectedGrammar();
signals:
     void Sign_HitList_ItemSelected(const QString &grammar, int index);

public slots:

//........................................... DATA ...............................................................
private:
  QFrame     *m_MainQFrame;
  int         m_Grid_H;
  QStringList m_grammarList;
  QWidget    *m_FocusWidget;
};

class C_Frm_Produit;
class QTextEdit;

//======================== C_Frm_Posologie =============================
class C_Frm_Posologie : public QFrame, C_PosologieGrammar
{
    Q_OBJECT

public:
    enum mode {
        NO_GRAB,
        BOTTOM_START,
        TOP_START,
        MIDLE_START
    };
    enum viewProfil {
        MATIN        = 1,         // matin
        MIDI         = 2,          // midi
        A_MIDI       = 4,        // apre-midi
        SOIR         = 8,
        COUCHER      = 16,
        NUIT         = 32,
        RENOUVELABLE = 64,
        NOTE         = 128,
        ALL_WIDGETS  = 255
    };
    enum modeProfil {
        PROFIL_ADD     = 1,
        PROFIL_DEL     = 2,
        PROFIL_SET     = 3
    };

    C_Frm_Posologie(  C_BDM_Api           *pC_BDM_Api,          // pointeur sur l'API medicamenteuse
                      C_Frm_Produit       *pC_Frm_Produit,      // on differencie le produit a traiter du parent (permet d'avoir pour parent n'importe quel autre objet)
                      C_BitMapCollection  *pC_BitMapCollection, // il nous faut des icones
                      QRect                geometry_rect,       // c'est le parent qui decide de la geometrie
                      QWidget             *parent,              // le pere
                      bool                 gridvisibility = false, // visibilite de la grille horizontale
                      int                  viewProfil     = C_Frm_Posologie::ALL_WIDGETS
                     );
    ~C_Frm_Posologie();
    void     paintEvent        ( QPaintEvent * event );
    void     mousePressEvent   ( QMouseEvent * event);
    void     mouseReleaseEvent ( QMouseEvent * event );
    void     mouseMoveEvent    ( QMouseEvent * event );
    void     mouseMoveEvent    ( QMouseEvent * event , QWidget *pQWidget );
    int      timeToPos_x(int nb_mn);
    int      doMenuButtonTimeMeal(const QString &name);
    QString  retPopupMomentMealToGrammarString(int ret);
    QString  interfaceToGrammarString();
    void     grammarToInterface();
    void     sequenceToInterface(      const QString &sequence, int index);
    void     sequenceTimeToInterface(const QString &sequence, int index);
    void     sequenceDaysToInterface(const QString &sequence, int index);
    int      sequenceHoursToInterface(const QString &before, const QString &after, const QString &value);
    void     clearInterface();
    void     adjustToSize(const QRect &geometry_rect);
    void     setGridVisibility(bool visibility   = false );
    void     setViewProfil(int viewProfil        = C_Frm_Posologie::ALL_WIDGETS, int profilMode =  C_Frm_Posologie::PROFIL_SET);
    int      getViewProfil(){return m_viewProfil;}
    void     adjustViewToProfil(int viewProfil);
    int           countVisiblesLineEdit();
    QStringList   getHitsList();
    C_Frm_PosologieHitList *get_C_Frm_PosologieHitList(){return m_HitList;}
    CMyQLineEdit *nextEnterFocus(CMyQLineEdit *pCMyQLineEdit);

    QTextEdit     *m_textEdit;
    CMyButton     *m_ButtonMatin;
    CMyButton     *m_ButtonMidi;
    CMyButton     *m_ButtonApresMidi;
    CMyButton     *m_ButtonSoir;
    CMyButton     *m_ButtonCoucher;
    CMyButton     *m_ButtonNuit;

    CMyButton     *m_ButtonSequencelist;
    CMyButton     *m_ButtonSequenceAdd;
    CMyButton     *m_ButtonSequenceDel;

    CMyButton     *m_ButtonPeriode;
    CMyButton     *m_ButtonPeriodeUnit;

    CMyQLineEdit  *m_LineEditMatin;
    CMyQLineEdit  *m_LineEditMidi;
    CMyQLineEdit  *m_LineEditApresMidi;
    CMyQLineEdit  *m_LineEditSoir;
    CMyQLineEdit  *m_LineEditCoucher;
    CMyQLineEdit  *m_LineEditNuit;
    CMyQLineEdit  *m_LineEditPeriode;
    QList <CMyQLineEdit*> m_ListEnterFocusEdit;
private:

  int             m_Hdeb_mn;
  int             m_Hfin_mn;
  int             m_first_time;
  int             m_grad_pos_y;
  int             m_grad_w;
  int             m_grad_h;
  int             m_GrabIsOn;
  int             m_startPosY;
  int             m_rightMarg;            /*!< marge droite pour affichage icones */
  int             m_viewProfil;           /*!< flag precisant l'affichage ou non des boutons après_midi coucher nuit*/

  QMap <QString,QString> m_MomentMealMap;    /*!< "matin""r30" "soir""15s*/
  C_BDM_Api             *m_pC_BDM_Api;
  C_Frm_Produit         *m_pC_Frm_Produit;
  C_BitMapCollection    *m_pC_BitMapCollection;
  QPointer<C_Frm_PosologieHitList>  m_HitList;

public slots:
  void Slot_adjustViewToProfil();
  void Slot_LineEdit_focusIn     (const QString &name,  CMyQLineEdit *pCMyQLineEdit, void *ptr);
  void Slot_LineEdit_focusOut    (const QString &name,  CMyQLineEdit *pCMyQLineEdit, void *ptr);
  void Slot_returnLineEditPressed(const QString &name,  CMyQLineEdit *pCMyQLineEdit, void *ptr, Qt::KeyboardModifiers modifiers);
  void Slot_ButtonMatinClicked(          const QString &, void *);
  void Slot_ButtonMidiClicked(           const QString &, void *);
  void Slot_ButtonApresMidiClicked(      const QString &, void *);
  void Slot_ButtonSoirClicked(           const QString &, void *);
  void Slot_ButtonCoucherClicked(        const QString &, void *);
  void Slot_ButtonNuitClicked(           const QString &, void *);

  void Slot_LineEditMatin_textChanged(       const QString &);
  void Slot_LineEditMidi_textChanged(        const QString &);
  void Slot_LineEditApresMidi_textChanged(   const QString &);
  void Slot_LineEditSoir_textChanged(        const QString &);
  void Slot_LineEditCoucher_textChanged(     const QString &);
  void Slot_LineEditPeriode_textChanged(     const QString &);
  void Slot_LineEditNuit_textChanged(        const QString &);

  void Slot_ButtonSequencelistClicked(   const QString &, void *);
  void Slot_ButtonSequenceAddClicked(    const QString &, void *);
  void Slot_ButtonSequenceDelClicked(    const QString &, void *);
  void Slot_ButtonPeriodeClicked(        const QString &, void *);
  void Slot_ButtonPeriodeUnitClicked(    const QString &, void *);
  void Slot_HitList_ItemSelected(const QString &grammar,  int index);
signals:
  void Sign_child_LeaveLastEditZone();
};

//======================== C_Frm_Produit =============================
class C_Frm_Produit : public QFrame, public C_OrdoLineRecord
{
    Q_OBJECT

public:
    enum mode {
        NO_GRAB,
        BOTTOM_START,
        TOP_START,
        MIDLE_START
    };

    C_Frm_Produit(  C_Frm_Produit     const  &c_Frm_Produit);
    C_Frm_Produit(  C_OrdoLineRecord  const  &ordoLineRecord ,
                    C_BDM_Api           *pC_BDM_Api,
                    QRect                geometry_rect,
                    QWidget             *parent       ,
                    const QString       &background_noALD = "#ffe3be",
                    const QString       &background_isALD = "#f5ffbe",
                    bool                 gridvisibility   = false,
                    int                  viewProfil       = C_Frm_Posologie::ALL_WIDGETS
                    );// visibilite de la grille horizontale
    ~C_Frm_Produit();
    void              paintEvent        ( QPaintEvent * event );
    void              mousePressEvent   ( QMouseEvent * event);
    void              mouseReleaseEvent ( QMouseEvent * event );
    void              mouseMoveEvent    ( QMouseEvent * event );
    void              mouseMoveEvent    ( QMouseEvent * event , QWidget *pQWidget );

    C_OrdoLineRecord  ordoLineRecord() const;
    void              complete_C_OrdoLineRecord();
    void              setOrderNumber(int num);
    bool              isInDragAction() {return m_GrabIsOn;}
    QColor            backGroundColor(){QColor                background_color = ald().length()?m_background_isALD:m_background_noALD;
                                        if (isInDragAction()) background_color = background_color.darker(110);
                                        return                background_color;
                                       }
    void              adjustToSize(const QRect &rect);
    void              setColors(const QString &_std_color, const QString &_ald_color);
    void              setGridVisibility(bool visibility = false);
    void              setViewProfil(int viewProfil  = C_Frm_Posologie::ALL_WIDGETS , int profilMode =  C_Frm_Posologie::PROFIL_SET)
                                   { if (m_pC_Frm_Posologie) m_pC_Frm_Posologie->setViewProfil(viewProfil,profilMode);
                                   }
    int               getViewProfil(){if (m_pC_Frm_Posologie)return m_pC_Frm_Posologie->getViewProfil();
                                      else                   return -1;}

    //............ public members datas ..............................
    CMyButton          *m_ButtonDelete;
    CMyButton          *m_ButtonNumber;
    C_Frm_Posologie    *m_pC_Frm_Posologie;


private:
  int                 m_GrabIsOn;;
  int                 m_startPosY;
  QColor              m_background_isALD;
  QColor              m_background_noALD;
  C_BDM_Api          *m_pC_BDM_Api;

public slots:
signals:

};

//============================= C_Frm_Prescription ==============================================
class C_Frm_Prescription : public QFrame , public C_BitMapCollection
{

 Q_OBJECT
public:
    enum mode {
        ALL_POSITIONS_BELOW_Y     = -1,
        JUST_ONE_POSITION_UNDER_Y =  0
    };

    C_Frm_Prescription(const QString &imagePath, C_BDM_Api *pC_BDM_Api , QScrollArea *pQScrollArea , QWidget *parent=0 );

    void                     paintEvent    ( QPaintEvent *event );
    void                     mouseMoveEvent( QMouseEvent *event );
    int                      adjust_Vertical_PositionToGrid(C_Frm_Produit *pC_Frm_Produit  = 0, bool scroll_if_out_limits=false);
    int                      adjust_Vertical_PositionToGrid(int y, C_Frm_Produit *pC_Frm_Produit  = 0 );
    void                     objectStartsMoving(C_Frm_Produit *pC_Frm_Produit);
    void                     objectDoMoving(C_Frm_Produit *pC_Frm_Produit);
    void                     objectStopsMoving(C_Frm_Produit *pC_Frm_Produit);
    void                     deplace_Objects(int y_ref, int ofset_y);
    void                     rearangeAllNumberOrder(QList<C_Frm_Produit*> *pListProduitExcluded   = 0 );
    int                      count_ALD(int *nb_Prd = 0 );
    int                      count_GridToDraw(int *nb_ald_toRet  = 0 );
    bool                     is_posY_in_ALD_Zone();
    bool                     is_posY_in_ALD_Zone(int y);
    void                     echoListObjects(const QString txt);
    void                     setZoom(int steep);
    void                     appendNewObject(const QString &xmlData);
    void                     appendNewObject(const QString &xmlData, int pos_y);
    QList <C_Frm_Produit*>   C_Frm_ProduitList();
    QSize                    getChildsSize();
    void                     setChildsSize(int childs_w, int childs_h);
    void                     setChildsColors(const QString &std_color, const QString &ald_color);
    void                     setChildsGridVisibility(bool visibility = false);
    int                      setChildsViewProfil(int viewProfil = C_Frm_Posologie::ALL_WIDGETS, int mode = C_Frm_Posologie::PROFIL_SET);
    int                      getChildsViewProfil(){return m_childs_ViewProfil;}
    //------------------------------------ objectListAt ------------------------------------------------
    /*! \brief return objects list under y_ref to y_end positions
     *  \param  y_ref start Y position.
     *  \param  y_end end   Y position. if -1 then alls positions below y_ref, if zero just one position under y_ref
     *  \param  QList<C_Frm_Produit*> *pListProduitExcluded if not zero this objects from this list will be excluded from result list.
     *  \return QList <C_Frm_Produit*>  result list
     */
    QList <C_Frm_Produit*>   objectListAt(int y_ref, int y_end = 0, QList<C_Frm_Produit*> *pListProduitExcluded   = 0 );
    //------------------------- gestion du drag & drop ---------------------------------------
    void                     dropEvent(       QDropEvent      *event );
    void                     dragEnterEvent(  QDragEnterEvent *event );
    void                     dragMoveEvent(   QDragMoveEvent  *event );
    void                     dragLeaveEvent ( QDragLeaveEvent *event );
    QString                  get_DropedXmlDatas()                        {return m_XmlDatas;}
    void                     set_DropedXmlDatas(const QString &xmlDatas) {m_XmlDatas=xmlDatas;}
    void                     clear_DropedXmlDatas()                      {m_XmlDatas="";}
private:

    C_BDM_Api      *m_pC_BDM_Api;                /*!< pointeur sur C_BDM_Api api des la base de donnees medicamenteuse */
    QScrollArea    *m_pQScrollArea;              /*!< pointeur sur l'objet QScrollArea (faire scroller lors deplacements des C_Frm_Produit)  */
    QString         m_str_background_isALD;      /*!< couleur par defaut des objets enfants ald */
    QString         m_str_background_noALD;      /*!< couleur par defaut des objets enfants non ald */
    QPoint          m_startDragPos;              /*!< position de demarrage lors deplacementC_Frm_Produit        */
    int             m_lastDragPosY;              /*!< derniere position en cours lors deplacementC_Frm_Produit   */
    QString         m_mimeType;                  /*!< type donnees recues lors du drag & drop     */
    QString         m_XmlDatas;                  /*!< donnees xml recues lors du drag & drop      */
    QString         m_mimeTypeIconPath;          /*!< chemin des icones                 (definie) */

    int             m_Nb_Grid_H;                 /*!< nombre de cases maximum           (definie) */
    int             m_SpaceBetweenProduits;      /*!< marge entre deux case             (definie) */
    int             m_C_Frm_Produit_W;           /*!< hauteur d'un objet C_Frm_Produit  (definie) */
    int             m_C_Frm_Produit_H;           /*!< largeur d'un objet C_Frm_Produit  (definie) */
    int             m_Grid_H;                    /*!< hauteur d'une case (calculee avec m_C_Frm_Produit_H + m_SpaceBetweenProduits) */
    bool            m_childs_HGridVisibility;    /*!< visibilite de la grille horizontale C_Frm_Produit  (definie) */
    int             m_childs_ViewProfil;         /*!< profil de la vue des posologies  */
    //QPointer<C_Frm_Produit>  m_pC_Frm_ProduitDrag;
public slots:
    void            Slot_Drop_Prd();
    void            Slot_ButtonDeleteClicked(const QString&, void*);
    void            Slot_ButtonNumberClicked(const QString&, void*);

signals:
    void Sign_child_LeaveLastEditZone();
};

#endif // C_FRM_PRESCRIPTION_H
