/***********************************************************************
 * FXRuby -- the Ruby language bindings for the FOX GUI toolkit.
 * Copyright (c) 2001-2003 by J. Lyle Johnson. All Rights Reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * For further information please contact the author by e-mail
 * at "lyle@users.sourceforge.net".
 ***********************************************************************/

class FXHVec {
public:
  /// Default constructor
  FXHVec();

  /// Copy constructor
  FXHVec(const FXHVec& w);

  /// Initialize with 3-vector
  FXHVec(const FXVec& w);

  /// Initialize with components
  FXHVec(FXfloat x,FXfloat y,FXfloat z,FXfloat w=1.0f);

  /// Initialize with color
  FXHVec(FXColor color);

  // Other good stuff
  %extend {
    FXfloat __getitem__(FXint i){
      if(i<0||i>3){
        rb_raise(rb_eIndexError,"index %d out of bounds",i);
        return 0.0f;
        }
      else
        return (*self)[i];
      }
    FXfloat __setitem__(FXint i,FXfloat f){
      if(i<0||i>3) rb_raise(rb_eIndexError,"index %d out of bounds",i);
      (*self)[i]=f;
      return f;
      }
  
	// Negation
	FXHVec operator-() const { return -(*self); }
  
	// Addition
	FXHVec operator+(const FXHVec& b) const { return (*self)+b; }

	// Subtraction
	FXHVec operator-(const FXHVec& b) const { return (*self)-b; }
  
	// Multiply by a scalar
	FXHVec operator*(FXfloat n) const { return (*self)*n; }

	// Divide by a scalar
	FXHVec operator/(FXfloat n) const {
	  if(n==0.0f) rb_raise(rb_eZeroDivError,"divided by 0");
	  return (*self)/n;
	  }

	/// Dot product
	FXfloat operator*(const FXHVec& a) const { return (*self)*a; }

	/// Equality tests
	bool operator==(const FXHVec& b) const { return (*self == b); }
	bool operator==(FXfloat n) const { return (*self == n); }

	// Other functions
    FXfloat dot(const FXHVec& other) const { return (*self)*other; }
    FXfloat len() const { return len(*self); }
    FXHVec normalize() const { return normalize(*self); }
    FXHVec lo(const FXHVec& other) const { return lo(*self,other); }
    FXHVec hi(const FXHVec& other) const { return hi(*self,other); }

	FXString to_s() const {
      const FXHVec& v = *self;
      return FXStringFormat("[%g, %g, %g, %g]",v[0],v[1],v[2],v[3]);
      }
    VALUE to_a(){
      VALUE ary=rb_ary_new();
      rb_ary_push(ary,to_ruby((*self)[0]));
      rb_ary_push(ary,to_ruby((*self)[1]));
      rb_ary_push(ary,to_ruby((*self)[2]));
      rb_ary_push(ary,to_ruby((*self)[3]));
      return ary;
      }
    }
  };
