/***************************************************************************
 *   Copyright (C) 2004 by Armando Navarro-Vazquez                         *
 *   qoajnv@usc.es                                                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef KRYOVISOR_H
#define KRYOVISOR_H

#include "glvisorbase.h"
#include "quantumparser.h"
//Added by qt3to4:
#include <QWheelEvent>
#include <QMouseEvent>
#include <Q3PopupMenu>
#include <iostream>
#include "kryomolcore_export.h"
/**
@author Armando Navarro-Vazquez
*/
/** Spetialization for the KryoMol Plugin*/

enum eSelectionMode { eNone,  eJ, eDistance, eAngle, eDihedral, eAnglePlanes, eRotateBond, eCreateBond,eDeleteBond, eAddGroup, eRenumberAll, eRenumberHeavy, eSetDihedral, eGromacs3dout };

class Q3PopupMenu;
class Animation;
class KRYOMOLCORE_EXPORT KryoVisor : public CGlVisorBase
{
 Q_OBJECT
public:
   KryoVisor(QWidget* parent =0);

   virtual ~KryoVisor();

  void SetSelectionMode(eSelectionMode mode);
  eSelectionMode SelectionMode() const { return m_selectionmode; }
  virtual void Initialize();
  void Export(const QString& file, const QString& mode);
  
signals:
  void selectedPoint(int );
  void playing(bool );
public slots:
  void OnSelectionNone() { m_selectionmode=eNone; OnResetSelection(true);}
  void OnClearDistances();
  void OnMeasureDistances(bool b);
  void OnMeasureAngles(bool b);
  void OnMeasureDihedrals(bool b);
  void OnMeasureAngleBetweenPlanes(bool b);
  void OnRenumbering(bool b);
  void OnSetDihedral(bool b);
  void OnGromacs3dout(bool b);
  void OnRotateBond(bool b);
  void OnCreateBond(bool b);
  void OnDeleteBond(bool b);
  void OnAddGroup();
  virtual void OnStartAnimation();
  virtual void OnStopAnimation();
  void OnSelectPoint(int current);
  void OnFirstFrame();
  void OnLastFrame();
  void OnPreviousFrame();
  void OnNextFrame();
  
protected:
  virtual void OnSelection(QMouseEvent* e);
  //virtual void RenderButtons();
  virtual void RenderScreenText();
//  virtual void (const QPoint& pos);
  virtual void mousePressEvent(QMouseEvent* e);
  virtual void wheelEvent(QWheelEvent* e);
  virtual void mouseMoveEvent(QMouseEvent* e);
  virtual void RenderMolecule(GLenum mode=GL_RENDER);
  virtual QSize sizeHint() const { return QSize(640,480); }
private:
  /** Change hydrogen by a methyl group, this should be substitued for a more general function*/
  void ChangeHByMethyl(int i);
  void RenumberAtoms();
  void Gromacs3dout(int i, int j, int k, int l);
  std::vector<coordinate> CalculateCellCube();
protected slots:
    /** write ACES input */
  void OnExportACES();
  /** Export XYZ file to clipboard*/
  void OnExportXYZ();
  /** write CPMD input file to clipboard*/
  void OnExportCPMD();
  void OnExportGaussian(bool withhessian = false);
  /** show distances*/
  void OnShowDistances();
  /** show dipole*/
  void OnShowDipole();
  void OnShowCell();
  void OnResetSelection(bool repaint =true);
  void OnEnantiomerize();
  void OnRecalculateConnectivity();
  void OnMoveToCentroid();
  void OnShowESPCharges();
 protected:
  void RefreshDistances();
protected:
 // std::vector<CMolecule::pair> m_jpairs;
  std::vector<CMolecule::pair> m_rpairs;
  std::vector<CMolecule::triad> m_angletriads;
  std::vector<CMolecule::quad> m_dihedralquads;
  Q3PopupMenu* m_exportmenu;
  /** Show dipole on the screen*/
  bool m_bshowdipole;
  bool m_bshowcell;
  /** Show bond lenghts on screen*/
  bool m_bshowdistances;
 eSelectionMode m_selectionmode;
  QTimer* m_timer;
  int m_framespeed;
  std::vector< std::vector<CMolecule::Coupling>::const_iterator > m_jpairs;
  unsigned int  m_nheavyatoms;
private:
  Q3PopupMenu* m_distancemenu;
  Q3PopupMenu* m_chargemenu;
  bool m_bshowespcharges;
};


class KRYOMOLCORE_EXPORT KryoVisorOpt : public KryoVisor
{
Q_OBJECT
  public:
  KryoVisorOpt(QWidget* parent=0) ;
  virtual ~KryoVisorOpt() {};
  virtual void Initialize();
public slots:
  void OnForceScale(float f) { m_forcescale=f; update(); }
  protected:
 // virtual void RenderButtons();
//  virtual void selectButton(const QPoint& pos);
  virtual void RenderScreenText();
  virtual void RenderMolecule(GLenum mode=GL_RENDER);
protected slots:
  void OnShowForces();
  void OnChangeFrame();
protected:
  float m_forcescale;
  float m_forcemagnitude;
  bool m_bshowforces;
};

class QPNGMovie;
class KRYOMOLCORE_EXPORT KryoVisorFreq : public KryoVisor
{
  Q_OBJECT
  public:
  KryoVisorFreq(QWidget* parent=0);
  virtual ~KryoVisorFreq();
  virtual void Initialize();
  bool IsPlaying() const; 
  public slots:
  void SetMode(int mode,int frame);
  //virtual void OnStartAnimation();
  //virtual void OnStopAnimation();
  void RecordMovie(bool);
  void OnDistortion(int);
  virtual void OnStartAnimation();
  virtual void OnStopAnimation();
//   signals:
//   /** emited when vibrational modes are animated or stopped*/
//   void playing(bool);
  private slots:
  void OnPushImage();
  void OnExportGaussianWithHessian() { OnExportGaussian(true); }
  protected:
  //virtual void RenderButtons();
  virtual void RenderScreenText();
//  virtual void selectButton(const QPoint& pos);
  Animation* m_animation;
  //QPNGMovie* m_movie;
};

class KRYOMOLCORE_EXPORT KryoVisorDens : public KryoVisor
{
Q_OBJECT
public:
  KryoVisorDens(QWidget* parent=0);
  virtual ~KryoVisorDens();
protected slots:
  void OnShowAIMCharges();
  void OnShowAttractors();
  void OnShowBondPoints();
  void OnShowRingPoints();
  void OnRecalculateConnectivity();
protected:
 virtual void RenderMolecule(GLenum mode =GL_RENDER);
// virtual void RenderButtons();
 virtual void RenderScreenText();
 bool m_bshowattractors;
 bool m_bshowbondpoints;
 bool m_bshowringpoints;
 bool m_bshowaimcharges;
 Q3PopupMenu* m_aimmenu;
 Q3PopupMenu* m_cpmenu;
};

class NMRHandler;
class KRYOMOLCORE_EXPORT KryoVisorNMR : public KryoVisor
{
  Q_OBJECT
public:
  KryoVisorNMR(QWidget* parent=0);
  virtual ~KryoVisorNMR();
  virtual void Initialize(); 
public slots:
  void OnSetReferences(const NMRHandler* );
protected:
 virtual void RenderMolecule(GLenum mode=GL_RENDER);
protected slots:
  void OnShowChemicalShifts();
  void OnGetJs();

protected:    

protected:
  Q3PopupMenu* m_nmrmenu;
  bool m_bshowchemicalshifts;
  bool m_bgetjs;
 private:
   std::vector<float> m_shieldings;
};

template <class X> class KryoVisorFactory
{
  public:
  static X* BuildVisor(QWidget* parent)
  {
   return new X(parent);
  }
};
#endif
