// cBall.h
// 2/27/04
// Forrest Briggs
/// The ball class stores its position, velocity and radius.
// It knows how to draw itself, and check if it will intersect
// with a face, edge or vertex while moving from one place
// to another
// 3/1/04
// Andrew Kim
// Wrote edge and vertex intersection code.
// Ben Pellow
// Wrote face intersection code.
// Forrest Briggs
// Tested and debugged Ben and Andrew's code, wrote update() for ball.
// 3/5/04
// Forrest Briggs
// Updated face collision code to reflect Z's posted bugfix and fixed a bug 
// in the v1-v2 edge in face collision. fixed a bug in the collision response
// code that caused the ball to fall through the triangle by adding gravity
// after recursive update call.
// 3/12/04
// Forrest Briggs 
// Many many many bug fixes. Completely rewrote ball update cycle.
// Collision and sliding implemented and tested in with 1 triangle, 3 triangle
// pyramid and 2 pyramid ramp.
// 3/23/04 Forrest Briggs
// Ball collision code uses octree collider lists, no more sliding. Vastly simplifed code.

#ifndef cball_h
#define cball_h

#include "ForwardDeclarations.h"
#include "OGLPlatformSpecific.h"
#include "cVector.h"
#include "cTriangle.h"
#include "cEdge.h"
#include "cVertex.h"
#include "cStaticTriangleMesh.h"
#include "cIntersectionResult.h"
#include "cParticleSystem.h"
#include "cSplashParticle.h"
#include "cSmokeRingParticle.h"

class cBall
{
public:
    cVector position_, velocity_; 
    float radius_;
    
    cBall();
    ~cBall();
    
    void update(float dt, cStaticTriangleMesh& staticObjexcts);
    void draw();
    void randomize(int level = -1);
    
    void drawLaunchArrow(); // draws an arrow in the direction that the ball will be launched by pressing space
    void launch();
    
    float launchAngle_; 	// used to keep track of time to rotate hit arrow
    float launchPower_;		// the value of the ticker when the ball went into launche mode 1 (power)
    
    cParticleSystem* ps_;
    
    int level_;
    
    bool isInHole();
    float getTimeInHole();
    
private:    
    cVector lastPosition_;

    cIntersectionResult quadratic(float A, float B, float C);
    
    // cylces through all faces, edges and vertices respectively checking for
    // the nearest intersection and keeping track of the correct normal
    // modifies referenced variables.
    void collideFaces(	vector<cTriangle*>& triangles,
                        cVector& position_, cVector& newPosition,
                        cIntersectionResult &closestIntersection, 
                        cVector &normal,
                        int &material);
                        
    void collideEdges(	vector<cEdge*>& edges,
                        cVector& position_, cVector& newPosition,
                        cIntersectionResult &closestIntersection, 
                        cVector &normal,
                        int &material);
                        
    void collideVertices(   vector<cVertex*>& vertices,
                            cVector& position_, cVector& newPosition,
                            cIntersectionResult &closestIntersection, 
                            cVector &normal,
                            int &material);
                            
    cIntersectionResult intersectsFace(cVector &start, cVector &end, cTriangle &face);
    cIntersectionResult intersectsEdge(cVector &start, cVector &end, cEdge &edge); 
    cIntersectionResult intersectsVertex(cVector &start, cVector &end, cVertex &vertex); 
                         
    float r_, g_, b_;
    
    cVector launchNormal_;
    
    cVector lastValidPosition_; // store this in case we fall off the map
    float smokingTime_;
    float timeLeftSmoking_;
    bool isInHole_;
    float timeInHole_;
    bool stopped_;
    int numUpdatesMovingSlow_;
    
    
};

#endif // end define cball_h
