/*
 ----------------------------------------------------------------------------
 "THE BEER-WARE LICENSE" (Revision 42):
 <daniel.kratzert@ac.uni-freiburg.de> wrote this file. As long as you retain
 this notice you can do whatever you want with this stuff. If we meet some day,
 and you think this stuff is worth it, you can buy me a beer in return.
 Daniel Kratzert
 ----------------------------------------------------------------------------
*/

#ifndef DSRGUI_H
#define DSRGUI_H

#include <QtGui>
#if (QT_VERSION >= 0x050000)
#include <QtWidgets>
#endif 
#include <QDialog>
#include <QModelIndex>
#include <QNetworkAccessManager>
#include <QNetworkSession>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUdpSocket>

class Window;
class Molecule;
class DSRGlWindow;
class DSREditWindow;

typedef struct DSRMol {
  // Data structure to hold the information getting from "DSR -ah name"
  QString tag;                  //!< the name tag
  QString comment;              //!< the name or first comment
  QString source;               //!< the source or reference
  QList<double> cell;           //!< unit cell
  QString residue;              //!< residue class
  QString dbtype;               //!< "dsr_db" or "dsr_usr_db"
  QStringList restr;            //!< list of restraints
  QVector<QStringList> atoms;   //!< list of atoms
} DSRMol;

class DSRGui : public QWidget
{
    Q_OBJECT

public:
  explicit DSRGui(Molecule *mole, QString shelxlPath, Window *parent = 0);
  DSREditWindow *editwindow;   //!< A window where you can edit a fragment
  DSRMol *header;              //!< The dsr header information of the current fragment
  QStringList SHXkeywords;     //!< A StringList of all SHELXL cards
  virtual ~DSRGui();
  DSRGlWindow *mygl;           //!< The 3D window of the current fragment
  void checkForDSRexecutable(QSplashScreen *splash);
  QSize minimumSizeHint() const;
  QSize sizeHint() const;
  static QString textWrap(QString inText, QString indent = QString("=\n  "));  //! wraps text after specific amount of characters with a line ending
private:
  QString getSelectedAtomsList();  //!< returns the list of the selected atoms in ShelXle
  QString getSelectedAtomsCoords();  //!< returns the coordinates of the selected atoms in ShelXle
  Molecule *m_molecule;            //!< A pointer to the molecule object in ShelXle
  Window *m_shelxle;               //!< The Window object of ShelXle
  QVector<QStringList> *fragmentsList;   //!< tag;;fullname;;line number;;db
  QTextBrowser *outtext;              //!< The message output field
  QTextBrowser *info;              //!< Information table with bond distances of fitted fragments
  QLineEdit *SearchInp;            //!< Search input field
  QLineEdit *occEdit;              //!< Input field for the SHELXL occupancy
  //QLineEdit *resinumEdit;          //!< Input field for residue numbers (obsolete, because is automatically determined)
  QLineEdit *resiclassEdit;        //!< Input field for the residue class
  QVBoxLayout *mainVLayout;
  QHBoxLayout *editLayout;
  QVBoxLayout *optionsLayout1;     //!< Layout for the PARt FVAR OCC replace options
  QVBoxLayout *optionsLayout2;     //!< Layout for invert external and rigid group options
  QVBoxLayout *optionsLayout3;     //!< Layout for the residue and user manual options
  QVBoxLayout *buttonLayout;       //!< Layout for fit, export and edit buttons
  QHBoxLayout *searchLayout;
  QHBoxLayout *partLayout;
  QHBoxLayout *fvarLayout;
  QHBoxLayout *occLayout;
  QHBoxLayout *resclassLayout;
  QGridLayout *chooserLayout;
  QHBoxLayout *optionboxes;
  QSpinBox    *partspinner; //!< part definition spinbox
  QSpinBox    *fvarspinner; //!< part definition spinbox
  QPushButton *editButton;  //! Button to start the fragment editor
  QPushButton *openLastButton; //! Button to open the last .res file version before last "DSR -r fileName" run.
  QPushButton *fitDSRButton;  //! Button to fit/transfer the fragment
  QPushButton *exportFragButton; //! Button to export the Fragment to a .res file
  QPushButton *splitButton;  //! Button to split the currently selected atoms on two positions
  QGroupBox *groupBox1;
  QGroupBox *groupBox2;
  QGroupBox *residueOptionsBox;
  QLabel *searchLabel,   //!<  The label for the search field
         *partLabel,
         *occLabel,
         *resiLabel,
         *classLabel,
         *resiTextLabel,
         *usermanualLabel;
  QPushButton *fvarLabel;   //! label for the free variable spinner (Is a button to be clickable)
  QTableView *fragmentTableView;   //!< list of fragments from DSR
  QString dsrResulttext;    //!< Resulting output text of a dsr run
  QString *resnumbertext;    //!< The text string that tells about the residue number
  QCheckBox *runExtBox,      //!< Enable external restraints button
            *invertFragBox,  //!< enable/disable inverted fragment coordinates
            *dfixBox,        //!< enable/disable rigid group instead of restraints
            *replaceModeBox, //!< enable replace mode
            *rigidBox,       //!< keep fragment as rigid AFIX 9 group and omit restraints
            *splitModeBox;   //!< Only for CF6 fragment. Enables spitting of pivot carbon atom
  bool runext;               //!< Should DSR write external restraints file?
  bool invert;               //!< Should DSr invert the coordinates?
  bool norefine;
  bool replace;
  bool rigid;
  bool resiIsEnabled;
  bool cf3;
  bool splitmode;
  QString export_dir;
  QString target_atoms;
  QString dfix;
  QString part;
  QString fvarocc;
  QString resistr;
  QString resinum;
  QString resiclass;
  QString fragmentNameTag;
  QString dsrpath, dsr_db_path;
  QString combiDSRline;
  void displayFragmentsList(QVector<QStringList>, QString);
  QString getDSRDir();
  QString getDSRdbDir();
  void connect_signals_and_slots();
  void setToolTips();
  QString m_shelxlPath;
  QString dsrVersion;
  QNetworkAccessManager *net_manager;
  QNetworkReply *reply; //! reply from the net_manager with the version information of DSR
  void getVersionFromServer();
  bool runTCPServer();
  QLabel *statusLabel;
  QTcpServer *tcpServer;
signals:
  void optionTextChanged(void);
  void fragmentSelected(void);
  void exportDirChanged(QString export_dir);
  void currentFragmentChanged(DSRMol header);
  void closed();

public slots:
  void aboutDSR();
  bool listDSRdbFragments(QString fav); // list fragments in the DB
  void runEditWindow();
  void setInfo(QString);
  bool getFragmentHeader(QString frag);
  int getCharWidth(int numchars);
  void activateFitButton(void);
  bool fitDSR(void);
  void fitDSRExtern(bool checked);
  void invertFrag(bool checked);
  void rigid_group(bool checked);
  void refineOrNot(bool checked);
  void replaceOrNot(bool checked);
  void setFragName(QModelIndex name);
  void searchFragment(QString searchName);
  bool exportFrag(QString dirname);
  void DFIX(bool checked);
  void setPART(int part);
  void setFvarOcc(void);
  void setResiClass(QString rclass);
  void combineOptionstext(void);
  void setExportDirDialog(void);
  bool isDSRVersionCorrect(QString version);
  QStringList readResfile();
  void resetSelection();
  int findFVARlines(QStringList *reslist);
  QVector<int> findDSRLines(QStringList *reslist);
  int decideDSRInsertLine(QStringList *reslist);
  QString findFreeResiNumber();
  QStringList which(QString programName = "dsr");
  QString loadFavoriteFragment();
  void writeFavorites(QString name);
  void updateTarget();
  void isDSRUpToDate(QNetworkReply* reply);//!< Interpretes the network reply for the check for updates (manual version)
  void updateDSR(void);
  void invertFvar();
  void splitDecide();
  void splitSelectedAtoms();
  bool runDSR(QString option, bool showresults=true, QString workdir="");
  bool open_last_fileversion();
  void ReadClientData();
protected:
  virtual void closeEvent(QCloseEvent * event);

protected slots:

private slots:



};




#endif // DSRGUI

