var Smallthing = Smallthing || {};

Smallthing.MyMath = function() {
}

Smallthing.MyMath.RandomRangeInt = function(min, max)
{
    return Math.floor(Math.random() * (max - min + 1)) + min;    
}

Smallthing.MyMath.RandomRangeFloat = function(min, max)
{
    return (Math.random() * (max - min + 1)) + min;    
}

Smallthing.MyMath.Lerp = function(v0, v1, t)
{
    return (1 - t) * v0 + t * v1;
}

Smallthing.MyMath.GetAngleFromPoints = function(p1, p2) {
    
    return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
}

Smallthing.MyMath.radians_to_degrees = function(radians)
{
  var pi = Math.PI;
  return radians * (180/pi);
}

Smallthing.MyMath.degrees_to_radians = function(degrees)
{
  var pi = Math.PI;
  return degrees * (pi/180);
}

Smallthing.MyMath.GetRadiansFromPoints = function(p1, p2) {
    
    return Math.atan2(p2.y - p1.y, p2.x - p1.x);
}

Smallthing.MyMath.GetAngleFromDirection = function(dir) {
    
    var angle = Math.atan2(dir.y, dir.x);   //radians
    // you need to devide by PI, and MULTIPLY by 180:
    var degrees = 180*angle/Math.PI;  //degrees
    return (360+Math.round(degrees))%360; //round number, avoid decimal fragments
}

Smallthing.MyMath.GetRadiansFromDirection = function(dir) {
    
    return Math.atan2(dir.y, dir.x);
}


// p1 and p2 are Phaser.Points
Smallthing.MyMath.GetDirection = function(p1, p2)
{
    var pt1 = new Smallthing.Point(p1.x, p1.y);
    var pt2 = new Smallthing.Point(p2.x, p2.y);
    
    var p = pt2.subtract(pt1.x, pt1.y);
    var o = new Smallthing.Point();
    
    Smallthing.Point.normalize(p, o);
    
    return o;
}

Smallthing.MyMath.Clamp = function (v, min, max) {

    if (v < min)
    {
        return min;
    }
    else if (max < v)
    {
        return max;
    }
    else
    {
        return v;
    }

},
    
Smallthing.MyMath.distance = function (x1, y1, x2, y2) {

    var dx = x1 - x2;
    var dy = y1 - y2;

    return Math.sqrt(dx * dx + dy * dy);
},

Smallthing.MyMath.RotatePoint = function(pointX, pointY, originX, originY, angle) {
    angle = angle * Math.PI / 180.0;
    return {
        x: Math.cos(angle) * (pointX-originX) - Math.sin(angle) * (pointY-originY) + originX,
        y: Math.sin(angle) * (pointX-originX) + Math.cos(angle) * (pointY-originY) + originY
    };
}

Smallthing.MyMath.GetRandomWithProbabilities = function(weights, results) {
    var r = Math.random(),
        index = weights.length - 1;

    weights.some(function (probability, i) {
        if (r < probability) {
            index = i;
            return true;
        }
        r -= probability;
    });
    return results[index];
}

//given "0-360" returns the nearest cardinal direction "N/NE/E/SE/S/SW/W/NW/N" 
Smallthing.MyMath.DegToCard8 = function(angle) {
    
    var k = 45 / 2;
    
    if(angle >= 90-k && angle < 90+k)
        return 'N';

    if(angle >= 45-k && angle < 45+k)
        return 'NE';

    if((angle >= 0 && angle < k) || (angle > 360-k && angle < 360))
        return 'E';

    if(angle >= (90+45)-k && angle < (90+45)+k)
        return 'NW';
    
    if(angle >= 180-k && angle < 180+k)
        return 'W';
    
    if(angle >= (180+45)-k && angle < (180+45)+k)
        return 'SW'; 
    
    if(angle >= 270-k && angle < 270+k)
        return 'S';    

    if(angle >= (270+45)-k && angle < (270+45)+k)
        return 'SE'; 
    
    return null;
}

Smallthing.MyMath.DegToCard16 = function(deg) {
    
  if (deg>11.25 && deg<33.75){
    return "NNE";
  }else if (deg>33.75 && deg<56.25){
    return "ENE";
  }else if (deg>56.25 && deg<78.75){
    return "E";
  }else if (deg>78.75 && deg<101.25){
    return "ESE";
  }else if (deg>101.25 && deg<123.75){
    return "ESE";
  }else if (deg>123.75 && deg<146.25){
    return "SE";
  }else if (deg>146.25 && deg<168.75){
    return "SSE";
  }else if (deg>168.75 && deg<191.25){
    return "S";
  }else if (deg>191.25 && deg<213.75){
    return "SSW";
  }else if (deg>213.75 && deg<236.25){
    return "SW";
  }else if (deg>236.25 && deg<258.75){
    return "WSW";
  }else if (deg>258.75 && deg<281.25){
    return "W";
  }else if (deg>281.25 && deg<303.75){
    return "WNW";
  }else if (deg>303.75 && deg<326.25){
    return "NW";
  }else if (deg>326.25 && deg<348.75){
    return "NNW";
  }else{
    return "N"; 
  }
}

Smallthing.MyMath.interpolatedPosition = function( P0, P1, P2, P3, u )	//Catmull-Rom interpolation

{

	var u3 = u * u * u;

	var u2 = u * u;

	var f1 = -0.5 * u3 + u2 - 0.5 * u;

	var f2 =  1.5 * u3 - 2.5 * u2 + 1.0;

	var f3 = -1.5 * u3 + 2.0 * u2 + 0.5 * u;

	var f4 =  0.5 * u3 - 0.5 * u2;

	var x = P0.x * f1 + P1.x * f2 + P2.x * f3 + P3.x * f4;

	var z = P0.z * f1 + P1.z * f2 + P2.z * f3 + P3.z * f4;

	return (new Vector(x, 0.0, z));

}

Smallthing.MyMath.savePathCatmullRom = function( path, step )	//main function to calculate the Path

{

    if ( path == null )

    return;

    var length = path.length;

    for ( var i = 0; i < length-1; i++ )

    {

        var ui = 0;

        for ( var u = 0.0; u < 1.0; u += step )

        {

            var vec = new Vector();

            vec = interpolatedPosition	//call to Catmull-Rom

            (

                path[ Math.max( 0, i-1 ) ], 	//Safe array steps

                path[ i ],

                path[ Math.min( i+1, length-1 ) ],//Safe Array steps

                path[ Math.min( i+2, length-1 ) ],//Safe Array steps

                u

            );

            outPath.push(vec);   //store each value

            nodesLeft++;	// increment node counter

            ui++;

        }

    }
}

rndInt = rndRangeInt = RandomRangeInt = Smallthing.MyMath.RandomRangeInt;
rndFloat = rndRangeFloat = RandomRangeFloat = Smallthing.MyMath.RandomRangeFloat;