var angle_increments = 10; // was 15. Phobos frames are 2 degrees apart; others are 5.
var ms_per_day = 12000;
var min_size = 2;

// Not yet handled:  changing the width between a_axis_radius and c_axis_radius
// depending on where it is in its orbit.  Need to figure out phasing.

function three_digits(n) {
  if (n < 10) return '00' + n;
  if (n < 100) return '0' + n;
  return n;
  }

function rounded_angle (angle) {
   return (Math.round(((angle/(2*Math.PI)*360)%360)
                                              /angle_increments)*angle_increments)%360;
}

function angle_url(angle) {
  return three_digits(angle)
}

function queue_preloaded_rotation (object,angle) {
   q = object.preloaded_rotation_queue;
   for (i in q) if (i==angle) return;
   // Note:  IE 5.1 on Mac does not support Array.push()
   q[q.length]=angle;
}

function preload_next_rotation (object) {
   // Note:  IE 5.1 on Mac does not support Array.shift() or pop()
   round_angle = object.preloaded_rotation_queue[object.rotation_queue_index++];
   if (round_angle==0 || round_angle) {
        image = new Image();
        image.src = object.url_prefix + angle_url(round_angle) + '.' + object.url_filetype;
        image.onload = function () {if (object.keep_preloading) preload_next_rotation(object)};
        object.preloaded_rotations[round_angle] = image;
   }
}

function preload_rotations (object, url_prefix, filetype) {
      object.keep_preloading = true;
      if (!filetype) filetype = 'png';
      if (!object.preloaded_rotations) {
         object.preloaded_rotation_queue = new Array();
         object.rotation_queue_index = 0;
         object.url_prefix = url_prefix;
         object.url_filetype = filetype;
         object.preloaded_rotations = new Array(360);
         for (angle=0; angle < 360; angle+= angle_increments*8)
               queue_preloaded_rotation(object,angle);
         for (angle=0; angle < 360; angle+= angle_increments*4)
               queue_preloaded_rotation(object,angle);
         for (angle=0; angle < 360; angle+= angle_increments*2)
               queue_preloaded_rotation(object,angle);
         for (angle=0; angle < 360; angle+= angle_increments*1)
               queue_preloaded_rotation(object,angle);
      }
}

function update_rotation (object, angle) {
    if (object.image_phasing) angle -= object.image_phasing*(2*Math.PI/360);
    rounded = rounded_angle(angle-Math.PI/2); // 000 means it's behind planet showing its near side
    if (rounded != object.currently_displayed_rotation) {
       image = object.preloaded_rotations[rounded];
       // if (!image) throw object.name + "@" + rounded + " has no preloaded image";
       if (image && image.complete) {
          object.image.src = image.src;
          object.currently_displayed_rotation = rounded;
       }
  }
}

function orbital_trajectory (center_x, center_y, radius, period, show_rotation, tilt, url_prefix) {
   this.id = next_trajectory_id++;
   if (!tilt) tilt = 0;
   this.update = function(object, ms) {
       if (show_rotation) { 
          preload_rotations(object,url_prefix);
          preload_next_rotation(object);
        }
        with (Math) {
           angle = 2*PI*(ms/ms_per_day)/period - PI*.4; // start almost behind planet
           distance_from_viewer = 1-sin(angle);
           object.image.style.zIndex = 2-round(distance_from_viewer);
           size_adjust = (1/(1+distance_from_viewer));
           if (show_rotation) update_rotation (object, angle);
           object.image.width = round(max(min_size,object.natural_width * size_adjust));
           object.image.height = round(max(min_size,object.natural_height * size_adjust));
           move_object_to(object, center_x + radius * -cos(angle),
                                                             (center_y + radius * tilt * sin(angle)) - object.image.height/2);
    }}
};

function rotation_trajectory (period,url_prefix, filetype) {
   this.id = next_trajectory_id++;
   this.update = function(object, ms) {
        preload_rotations (object, url_prefix, filetype);
        preload_next_rotation(object);
        update_rotation (object, 2*Math.PI*(ms/ms_per_day)/period);
    }
};
