//
//  globalForces.cpp
//  wablet
//
//  Created by Robert Tubb on 18/07/2011.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#include "globalForces.h"


//-----------------------------------------------------------
GlobalForces::GlobalForces(): grav(0.0,0.0){
    //construct
    gravityOn = true;
    
    speedLimit = 100.0;
    wallBounce = 0.5;
    
    pressureAmt = 0.0;
    gravityAmt = 0.2;
    touchStrength = 1.0;
    homingAmt = 0.0;
    avFilterAmt = 0.0;
    
    pressure = 0.0;
    volume = 2.0;
    
    maxForcePoints = 11;
    excitationType = POSITION;
    excitationShape = SINE;
    excitationStrength = 2;
    
    exciteShapeX = 2;
    exciteShapeY = 3;
    forceTouchPoints = new forceTouchPoint[maxForcePoints];
    for(int i = 0; i< 11; i++){
        forceTouchPoints[i].x = 0.0;
        forceTouchPoints[i].y = 0.0;
        forceTouchPoints[i].tid = -1;
        
    }
    
    
}

//-----------------------------------------------------------
GlobalForces::~GlobalForces(){
    //destruct
    
}
void GlobalForces::update(){
    // gravity 
    grav.setCoord(ofxAccelerometer.getForce().y * 0.015 * gravityAmt, ofxAccelerometer.getForce().x * 0.015 * gravityAmt);
    // time step
    delt = 1/ofGetFrameRate();
    
}
//-----------------------------------------------------------
// this is actually only called from dropletmesh.update
void GlobalForces::setPressure(double aP){
    
    pressure = pressureAmt*aP;
}
//-----------------------------------------------------------
void GlobalForces::createForceTouchPoint(double ax,double ay, int touchId){

    forceTouchPoints[touchId].x = ax;
    forceTouchPoints[touchId].y = ay;
    forceTouchPoints[touchId].tid = touchId; 

    
    
}
//-----------------------------------------------------------
void GlobalForces::moveForceTouchPoint(double ax,double ay, int touchId){
    //
    for(int i = 0;i<maxForcePoints; i++){
        if(forceTouchPoints[touchId].tid == touchId){
            forceTouchPoints[touchId].x = ax;
            forceTouchPoints[touchId].y = ay;            
        }
    }
    
}
//-----------------------------------------------------------
void GlobalForces::removeForceTouchPoint(int touchId){
    //
    for(int i = 0;i<maxForcePoints; i++){
        if(forceTouchPoints[i].tid == touchId){
            forceTouchPoints[i].tid = -1;          
        }
    } 
}
//-----------------------------------------------------------
TwoVector GlobalForces::getAllForceAt(double ax, double ay){
    //this is called for every mass point so work out most stuff in update()
    TwoVector force(0.0,0.0);
    double fmag, r;
    if(gravityOn){
        
        force.x += grav.x;
        force.y += grav.y;
    }
    
    // now touch points
     for(int i = 0;i<maxForcePoints; i++){
         // work out distance to force point and then use 1/r^2 rule 
         if(forceTouchPoints[i].tid != -1){
             TwoVector diff(forceTouchPoints[i].x - ax, forceTouchPoints[i].y - ay );
             r = diff.norm();
             if (r < 0.03){ // try avoid very small distances giving ridiculous forces
                 fmag = 0.0;
             }else{
                 fmag = touchStrength*1/(1000*(r*r));
             } 
            force.x -= fmag*diff.x/r;
            force.y -= fmag*diff.y/r;
             
         }
     }
    
    return force;
}
//-----------------------------------------------------------

Json::Value GlobalForces::convertToJsonForSaving(){
    
    Json::Value jgf;
    jgf["gravityOn"] = gravityOn;
    jgf["forceTouchOn"] = forceTouchOn;
    jgf["pressureOn"] = pressureOn;
    jgf["pressureAmt"] = pressureAmt;
    jgf["gravityAmt"] = gravityAmt;
    jgf["touchStrength"] = touchStrength;
    jgf["excitationStrength"] = excitationStrength;
    jgf["homingAmt"] = homingAmt;
    jgf["avFilterAmt"] = avFilterAmt;
    jgf["exciteShapeX"] = exciteShapeX;
    jgf["exciteShapeY"] = exciteShapeY;
    jgf["speedLimit"] = speedLimit;
    jgf["wallBounce"] = wallBounce;

    return jgf;
}
//-----------------------------------------------------------

void GlobalForces::setFromJson(Json::Value jgf){

    gravityOn = jgf["gravityOn"].asBool();
    forceTouchOn = jgf["forceTouchOn"].asBool();
    pressureOn = jgf["pressureOn"].asBool();
    pressureAmt = jgf["pressureAmt"].asDouble();
    gravityAmt = jgf["gravityAmt"].asDouble();
    touchStrength = jgf["touchStrength"].asDouble();
    excitationStrength = jgf["excitationStrength"].asDouble();
    homingAmt = jgf["homingAmt"].asDouble();
    avFilterAmt = jgf["avFilterAmt"].asDouble();
    exciteShapeX = jgf["exciteShapeX"].asInt();
    exciteShapeY = jgf["exciteShapeY"].asInt();
    speedLimit = jgf["speedLimit"].asDouble();
    wallBounce = jgf["wallBounce"].asDouble();

}
