#include "cardCollider.h"

bool intersectionTwoLines( ofPoint pt1, ofPoint pt2, ofPoint pt3, ofPoint pt4, ofPoint * iPt );
bool intersectionTwoLines( ofPoint pt1, ofPoint pt2, ofPoint pt3, ofPoint pt4, ofPoint * iPt )
{

    float ua =  ( (pt4.x-pt3.x)*(pt1.y-pt3.y) - (pt4.y-pt3.y)*(pt1.x-pt3.x) ) /
                ( (pt4.y-pt3.y)*(pt2.x-pt1.x) - (pt4.x-pt3.x)*(pt2.y-pt1.y) );

    float ub =  ( (pt2.x-pt1.x)*(pt1.y-pt3.y) - (pt2.y-pt1.y)*(pt1.x-pt3.x) ) /
                ( (pt4.y-pt3.y)*(pt2.x-pt1.x) - (pt4.x-pt3.x)*(pt2.y-pt1.y) );


    if( ua > 0 && ua < 1 && ub > 0 && ub < 1)
        ;
    else
        return false;

    iPt->x = pt1.x + ua * (pt2.x-pt1.x);
    iPt->y = pt1.y + ua * (pt2.y-pt1.y);

    return true;
}


bool pointInPolygon(float x, float y, vector<ofPoint>pts);
bool pointInPolygon(float x, float y, vector<ofPoint>pts)
{

	// code via Zach Lieberman via Randolph Franklin...
	int i, j, c = 0;
	int nPts = pts.size();

	for (i = 0, j = nPts-1; i < nPts; j = i++) {
	if ((((pts[i].y <= y) && (y < pts[j].y)) ||
	     ((pts[j].y <= y) && (y < pts[i].y))) &&
	    (x < (pts[j].x - pts[i].x) * (y - pts[i].y) / (pts[j].y - pts[i].y) + pts[i].x))
	  c = !c;
	}
	return (bool) c;
}

cardCollider::cardCollider()
{
    //ctor
}

cardCollider::~cardCollider()
{
    //dtor
}


void cardCollider::setup(){



    pt.setup( ofxVec3f(100,100,0), ofxVec3f(1.9,0,0),1);

}



void cardCollider::update(){
	
	pt.update();

    if( pt.pos.x > 640 ) pt.pos.x = 0;
    if( pt.pos.x < 0 ) pt.pos.x = 640;
    if( pt.pos.y > 480 ) pt.pos.y = 0;
    if( pt.pos.y < 0 ) pt.pos.y = 480;


}


void cardCollider::draw(){

    ofSetColor(0xffffff);
    pt.draw();
	
	
    ofSetColor(0xffff00); ofLine( intersectPoint.x,intersectPoint.y,velVec.x,velVec.y);

    ofCircle(intersectPoint.x,intersectPoint.y,1);



}


bool cardCollider::checkCardCollision( vector<ofPoint> cardContour, float radius ){


    bool bCollided = false;

    int totalPoints = cardContour.size();
    ofPoint sideA, sideB, ptReal, ptNext, iPt;

     for( int i = 0; i < totalPoints; i++)
     {
        sideA = cardContour[i];

        if( i == totalPoints - 1) sideB = cardContour[0];
        else                      sideB = cardContour[i+1];

        ofxVec3f vel = pt.vel;


        ptReal = ofxVec3f(pt.pos.x,pt.pos.y,pt.pos.z);
        ptNext = pt.pos + pt.vel*1.1;

        if( intersectionTwoLines( sideA, sideB, ptReal, ptNext, &iPt) )
        {
            // set new position to intersection  point
            pt.pos.set(iPt.x,iPt.y,0);

            intersectPoint = ofxVec3f(iPt.x,iPt.y,0);

            ofxVec3f sideDir = ofxVec3f(sideA.x,sideA.y,0)-ofxVec3f(sideB.x,sideB.y,0);
            float angleW = atan2(sideDir.y,sideDir.x);
            float angleV = atan2(pt.vel.y,pt.vel.x);
            float angleN = angleV - angleW;

            ofxVec2f newPoint;
            newPoint.x = cos(angleN);
            newPoint.y = sin(angleN);

            newPoint.y *= -1;

            float angleVl = angleW + atan2(newPoint.y, newPoint.x);
            ofxVec3f uVel = ofxVec3f( cos(angleVl), sin(angleVl), 0);

            velVec = intersectPoint + 100 * uVel;

            pt.vel = pt.vel.length()*uVel;
            pt.pos.x += pt.vel.x*0.03f;
            pt.pos.y += pt.vel.y*0.03f;

           bCollided = true;
           break;


        }


     }


     // check point in poly
     if( pointInPolygon( pt.pos.x, pt.pos.y, cardContour) )
     {
        // hack
        ofxVec3f dir = ofxVec3f(cardContour[0].x,cardContour[0].y,0)-ofxVec3f(pt.pos.x,pt.pos.y,0);
        pt.pos = ofxVec3f(cardContour[0].x,cardContour[0].y,0) + 2 * dir.normalized();
        pt.vel = pt.vel.length() * dir.normalized();
        bCollided = true;
     }

    return bCollided;




}


 void cardCollider::moveParticle( ofxVec3f dir )
 {
    pt.vel += dir;

 }
