/*
    ChemCon - molecular mechanics and molecular graphics
    Copyright (C) 1998-2002  Alexei Nikitin

    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 VIEWOBJ_H
#define VIEWOBJ_H

#ifndef ARRAY_H
#include "Array.h"
#endif

#ifndef VECT_H
#include "vect.h"   //fix
#endif

#ifndef LIGHT_MODEL_H
#include "Light_model.h"
#endif

#ifndef MATERIAL_H
#include "Material.h"
#endif

//namespace MM
//{

namespace MM
{
    class Atom;
    class Bond;
}

class View_atom_type;

//extern  int      View_coords_flag;

class View_object
  {
    private:  
      int                         selection_flag_;

    public:
      double                      x_, y_, z_;
      int                         X_, Y_, Z_;
      Material                    material_;
      double                      scale_;

      int                         is_selected()        { return selection_flag_; }
      void                        select()             { selection_flag_ = 1; }
      void                        unselect()           { selection_flag_ = 0; }
      void                        toggle_selection()   { selection_flag_ = !selection_flag_; }

      virtual void                set_attributes()=0;

      View_object() : selection_flag_(0), x_(0.0),y_(0.0),z_(0.0), X_(0),Y_(0),Z_(0)  { }
      virtual ~View_object();
  };

struct  View_object_handle
  {
    View_object        * ptr_;
    View_object        * operator->() { return ptr_; }

    int operator< ( View_object_handle obj ) { return ptr_->z_ <  obj->z_; }
    int operator<=( View_object_handle obj ) { return ptr_->z_ <= obj->z_; }
    int operator==( View_object_handle obj ) { return ptr_->z_ == obj->z_; }
    int operator>=( View_object_handle obj ) { return ptr_->z_ >= obj->z_; }
    int operator> ( View_object_handle obj ) { return ptr_->z_ >  obj->z_; }
  };

class View_abstract_sphere : public View_object
  {
    public:
      double                      radius_;
      int                         sector_flag_;

      virtual void                set_attributes() { throw; }

      View_abstract_sphere() : radius_( 0 )  { }
      virtual ~View_abstract_sphere();
  };

class View_abstract_line : public View_object
  {
    public:
      Vector                      point1_, point2_;

      virtual void                set_attributes() { throw; }
  };

//--------------------------------------------------------------------
class View_sphere : public View_abstract_sphere
  {
    private:
      double                      ix_,iy_,iz_,ir_;

    public:
      virtual void                set_attributes()  { x_ = ix_; y_ = iy_; z_ = iz_; radius_ = ir_; }

      View_sphere( double x, double y, double z, double r )
        : ix_(x), iy_(y), iz_(z), ir_(r) { }
      virtual ~View_sphere();
  };
//--------------------------------------------------------------------
/*
class View_atom_type : public Material
  {
  public:
    char                          name_[6];
    double                        radius_;

    View_atom_type();
    ~View_atom_type();
    View_atom_type( const View_atom_type & );
    const View_atom_type & operator = ( const View_atom_type & );

    //int                            operator == ( const VAtom_types & v ) const;
    //int                            operator != ( const VAtom_types & v ) const;
    //int                            operator < ( const VAtom_types & v ) const;

    void                          init( char * str );
  };

extern  View_atom_type    Selected_atom;
extern  View_atom_type    Default_atom;
//*/
//--------------------------------------------------------------------

class  View_Atom : public View_abstract_sphere
  {
    public:
      MM::Atom                  *atom_;
      View_atom_type            *view_type_;
//    Light_model               *LM;

      char                      symbol_[6];
      MM::Array <char>          label_;

      virtual void              set_attributes();

      View_Atom ();
      View_Atom (MM::Atom *);
      ~View_Atom();

      View_Atom (const View_Atom &);
      const View_Atom & operator = (const View_Atom &);
  };

//--------------------------------------------------------------------
class  View_Bond : public View_abstract_line
  {
    public:
//      Base_bonds                  *bond;
//      Base_atoms                  *atom_X;
//      Base_atoms                  *atom_Y;
      MM::Bond                  *bond_;
      MM::Atom                  *atom_X_;
      MM::Atom                  *atom_Y_;

      Material                  material_X_;
      Material                  material_Y_;

      virtual void              set_attributes();

      View_Bond();
      View_Bond (MM::Bond *);
      ~View_Bond();

      View_Bond( const View_Bond & );
      const View_Bond & operator = ( const View_Bond & );
  };


//--------------------------------------------------------------------
/*
class  Electrostatic
  {
      double                  ***potential;

    public:
      enum                    { plate, cube }  space_type;
      enum                    { colors, lines, dots }  rendering;
      double                  brightness;
      int                      show_flag, recalc_flag;

      Vectors                  O;
      int                      width, height, depth;
      double                  h;

      void                    calc();
      void                    set( double x, double y, double z, double value );
      double                  get( int X, int Y, int Z );
      double                  get( double x, double y, double z );

      void                    init();
      void                    init( Vectors o, double h_ );
      void                    init( Vectors o, int W, int H, int D, double h_ );
      void                    destroy();

      Electrostatic();
      ~Electrostatic();
  };

extern  Electrostatic    ElSt;
void    Calc_electrostatic();
void    Show_electrostatic();

inline  void    Electrostatic::
set( double x, double y, double z, double value )
  {
    int    X = ( x-O.x )/h,  Y = ( y-O.y )/h,  Z = ( z-O.z )/h;
    if( X < 0 || Y < 0 || Z < 0 || X >= width || Y >= height || Z >= depth )
      {
        MessageBox( NULL, "ElCube is out of range", "", IDOK );
        return;
      }
    potential[X][Y][Z] = value;
  }

inline  double  Electrostatic::
get( int X, int Y, int Z )
  {
     return potential[X][Y][Z];
  }

inline  double  Electrostatic::
get( double x, double y, double z )
  {
    int    X = ( x-O.x )/h,  Y = ( y-O.y )/h,  Z = ( z-O.z )/h;
    if( X < 0 || Y < 0 || Z < 0 || X >= width || Y >= height || Z >= depth )
      {
//        MessageBox( NULL, "ElCube is out of range", "", IDOK );
        return 0.0;
      }
    return potential[X][Y][Z];
  }

//--------------------------------------------------------------------

class  Electrostatic_plate : public View_object
  {
  public:
    double                        offset;

    virtual double                x_inner();
    virtual double                y_inner();
    virtual double                z_inner();

    Electrostatic_plate()  : offset( 0 )  { }
  };
extern  Electrostatic_plate  ElSt_plate;

inline double  Electrostatic_plate::x_inner()
  { return ElSt.width * ElSt.h / 2.0 + ElSt.O.x; }
inline double  Electrostatic_plate::y_inner()
  { return ElSt.height* ElSt.h / 2.0 + ElSt.O.y; }
inline double  Electrostatic_plate::z_inner()
  { return ElSt.depth * ElSt.h / 2.0 + ElSt.O.z + offset; }
*/

//}//MM

#endif//VIEWOBJ_H

