/***************************************************************************
 *   Copyright (C) 2005 by Roberto Virga                                   *
 *   rvirga@users.sourceforge.net                                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library 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 Library 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 KBSPREDICTORMOLECULEVIEW_H
#define KBSPREDICTORMOLECULEVIEW_H

#include <qdom.h>
#include <qgl.h>
#include <qmap.h>
#include <qstringlist.h>
#include <qtextstream.h>

#include <kbspredictordata.h>

class KBSPredictorMoleculeRenderer
{
  public:
    virtual ~KBSPredictorMoleculeRenderer() {}
    
    virtual void setColor(QColor color) = 0;
    virtual void drawBall(GLfloat *v, GLfloat radius) = 0;
    virtual void drawLine(GLfloat *v1, GLfloat *v2, GLfloat thickness=0) = 0;
    virtual void drawQuadrangle(GLfloat *v1, GLfloat *v2, GLfloat *v3, GLfloat *v4) = 0;
  
  protected:
    KBSPredictorMoleculeRenderer() {};
};

class KBSPredictorVRMLRenderer : public KBSPredictorMoleculeRenderer
{
  public:
    KBSPredictorVRMLRenderer(const QString &fileName);
    virtual ~KBSPredictorVRMLRenderer();
    
    virtual bool isOpen() const;
    virtual void close();
    
    virtual void setColor(QColor color);
    virtual void drawBall(GLfloat *v, GLfloat radius);
    virtual void drawLine(GLfloat *v1, GLfloat *v2, GLfloat thickness=0);
    virtual void drawQuadrangle(GLfloat *v1, GLfloat *v2, GLfloat *v3, GLfloat *v4);
  
  protected:
    QString m_color;
    QStringList m_lineCoords, m_lineColors, m_faceCoords, m_faceColors;
    QTextStream m_text;
  
  private:
    bool m_open;
};
    
class KBSPredictorX3DRenderer : public KBSPredictorMoleculeRenderer
{
  public:
    KBSPredictorX3DRenderer(const QString &fileName);
    virtual ~KBSPredictorX3DRenderer();
    
    virtual bool isOpen() const;
    virtual void close();
    
    virtual void setColor(QColor color);
    virtual void drawBall(GLfloat *v, GLfloat radius);
    virtual void drawLine(GLfloat *v1, GLfloat *v2, GLfloat thickness=0);
    virtual void drawQuadrangle(GLfloat *v1, GLfloat *v2, GLfloat *v3, GLfloat *v4);
  
  protected:
    QString m_color;
    QStringList m_lineCoords, m_lineColors, m_faceCoords, m_faceColors;
    QDomDocument m_doc;
    QDomElement m_group;
    QTextStream m_text;
  
  private:
    bool m_open;
};

class KBSPredictorMoleculeModel : public QObject
{
  Q_OBJECT
  public:
    KBSPredictorMoleculeModel(QObject *parent=0, char *name=0);
    virtual ~KBSPredictorMoleculeModel();
  
    enum Style { Backbone, Spline,
                 Wireframe, Sticks, Spacefill, BallAndStick };
    virtual Style style() const;
    virtual void setStyle(Style style);
    virtual bool isSupportedStyle(Style style) const;
    
    enum Coloring { Monochrome, Group, Shapely, CPK, Structure };
    virtual Coloring coloring() const;
    virtual void setColoring(Coloring coloring);
    virtual bool isSupportedColoring(Coloring coloring) const;
    
    virtual void setChain(const QValueList<KBSPredictorMonssterAtom> &chain);
    virtual void setSeq(const KBSPredictorMonssterSeq &seq);
    virtual void setPDB(const KBSPredictorProteinPDB &pdb);
    
    virtual void rotateData(int dx, int dy);
  
    virtual bool exportVRML(const QString &fileName) const;
    virtual bool exportX3D(const QString &fileName) const;
    
    friend class KBSPredictorMoleculeView;
  
  signals:
    void styleChanged();
    void coloringChanged();
    void dataChanged();
  
  protected:
    virtual void render(KBSPredictorMoleculeRenderer *renderer) const;
  
  private:
    void interpolateBackbone();
    
  protected:
    QValueList<KBSPredictorMonssterResidue> m_seq;
    QValueList<KBSPredictorAtomPDB> m_atoms;
    unsigned m_groups;
    
    GLfloat *m_backbone, *m_atom;
    
    static const unsigned s_divisions;
  
  private:
    Style m_style;
    Coloring m_coloring;
};

class KBSPredictorMoleculeView : public QGLWidget, KBSPredictorMoleculeRenderer
{
  public:
    KBSPredictorMoleculeView(QWidget *parent=0, char *name=0);
    virtual ~KBSPredictorMoleculeView();
     
    virtual void setColor(QColor color);
    virtual void drawBall(GLfloat *v, GLfloat radius);
    virtual void drawLine(GLfloat *v1, GLfloat *v2, GLfloat thickness=0);
    virtual void drawQuadrangle(GLfloat *v1, GLfloat *v2, GLfloat *v3, GLfloat *v4);
   
    virtual KBSPredictorMoleculeModel *model() const;
    
    virtual QPixmap pixmap();
 
 protected:
    virtual void initializeGL();
    virtual void resizeGL(int width, int height);
    virtual void paintGL();
    
    virtual void keyPressEvent(QKeyEvent *e);
    virtual void mousePressEvent(QMouseEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *e);
    virtual void mouseMoveEvent(QMouseEvent *e);
  
  protected:
    double m_scale;
    
  private:
    KBSPredictorMoleculeModel *m_model;
    
    bool m_tracking;
    QPoint m_last;
    
    GLUquadricObj *m_quadric;
    enum Shape { Sphere, Cylinder, Shapes };
    GLuint m_base;
};
    
#endif
