// Utilities () module
// utilities.js 
   console.log('UT version 2.40');
// 3:08 PM Thu June 18, 2020 
// Written by: James D. Miller 

/*
Dependencies for utilities.js:
   gwModule.js (gW.)
   constructorsAndPrototypes.js (cP.)
*/

(function() {
   
   "use strict";
   
   // Short names for Box2D constructors and prototypes
   var b2Vec2 = Box2D.Common.Math.b2Vec2;  
   
   
   // Returns the default if the value is undefined.
   function setDefault( theValue, theDefault) {
      return (typeof theValue !== "undefined") ? theValue : theDefault;
   }
   
   
   // Relationships between the screen and the b2d world ///////////////////////
   
   // Scaler conversions
   function meters_from_px( length_px) {
      return length_px / gW.c['px_per_m'];
   }
   
   function px_from_meters( length_m) {
      return Math.round(length_m * gW.c['px_per_m']);
   }

   // Vector conversions.
   function screenFromWorld( position_2d_m) {
      var x_px = px_from_meters( position_2d_m.x);
      var y_px = px_from_meters( position_2d_m.y);
      return new cP.Vec2D( x_px, gW.getCanvasDimensions().height - y_px);
   }
   
   function worldFromScreen( position_2d_px) {
      var x_m = meters_from_px(                 position_2d_px.x);
      var y_m = meters_from_px( gW.getCanvasDimensions().height - position_2d_px.y);
      return new cP.Vec2D( x_m, y_m); 
   }
 
   // Convert raw mouse value into the coordinates of the imaging element (iE), like the canvas for example.
   // If not in fullscreen mode, nudge it a little to account for the canvas border (5px) so that our mouse tip aligns with the Windows' mouse tip.
   function screenFromRaw_2d_px( imagingElement, raw_2d_px) {
      var mouse_iE_2d_px = new cP.Vec2D(0, 0);
      
      if (gW.c.fullScreenState) { 
         var renderedElementRect = {};
         // The magic is in this next line. The image scaling is limited by the axis that is most fractionally similar to the corresponding view-port axis.
         // Scaling that axis until it matches the view-port avoids clipping the image along the other axis.
         // So, take the minimum of the two ratios. That's the limit for scaling without clipping.
         var scaleFactor = Math.min( (window.innerHeight / imagingElement.height), (window.innerWidth / imagingElement.width) );
         renderedElementRect.width = imagingElement.width * scaleFactor; 
         renderedElementRect.height = imagingElement.height * scaleFactor; 
         
         renderedElementRect.left = Math.max( (window.innerWidth  - renderedElementRect.width)/2, 0);
         renderedElementRect.top  = Math.max( (window.innerHeight - renderedElementRect.height)/2, 0);
         // No canvas border here, so no "nudge" needed.
         mouse_iE_2d_px.x = Math.round( (raw_2d_px.x - renderedElementRect.left - 0) / scaleFactor);
         mouse_iE_2d_px.y = Math.round( (raw_2d_px.y - renderedElementRect.top - 0) / scaleFactor);
         
      } else {
         var renderedElementRect = imagingElement.getBoundingClientRect();
         // Nudge needed here.
         mouse_iE_2d_px.x = raw_2d_px.x - renderedElementRect.left - 5;
         mouse_iE_2d_px.y = raw_2d_px.y - renderedElementRect.top - 5;
      }
      return mouse_iE_2d_px;
   }
 
   // Functions to convert between vector types
   function Vec2D_from_b2Vec2( b2Vector) {
      return new cP.Vec2D( b2Vector.x, b2Vector.y);
   }
   function b2Vec2_from_Vec2D( vec2D) {
      return new b2Vec2( vec2D.x, vec2D.y);
   }
   
   // This check is useful to prevent problems (objects stripped of their methods) when reconstructing from a 
   // JSON capture.
   function Vec2D_check( vector_2d) {
      if (vector_2d.constructor.name == "Vec2D") {
         return vector_2d;
      } else {
         return new cP.Vec2D( vector_2d.x, vector_2d.y);
      }
   }
 
   
   // Reveal these functions to the global windows scope.
   window.setDefault = setDefault;
   
   window.worldFromScreen = worldFromScreen;
   window.screenFromWorld = screenFromWorld;
   window.screenFromRaw_2d_px = screenFromRaw_2d_px;
   window.Vec2D_from_b2Vec2 = Vec2D_from_b2Vec2;
   window.b2Vec2_from_Vec2D = b2Vec2_from_Vec2D;
   window.px_from_meters = px_from_meters;
   window.meters_from_px = meters_from_px;
   window.Vec2D_check = Vec2D_check;
   
})();