;+
; Project     :	Multimission
;
; Name        :	GET_SUNSPICE_CARR_DATE()
;
; Purpose     :	Convert Carrington rotation number to date
;
; Category    :	SUNSPICE, orbit
;
; Explanation :	Calculates the date corresponding to a specified Carrington
;               rotation number, either for Earth, or a spacecraft.
;
; Syntax      :	Date = GET_SUNSPICE_CARR_DATE(CARR_ROT, SPACECRAFT)
;
; Examples    :	Print, GET_SUNSPICE_CARR_DATE(2080.75, 'Ahead', /CCSDS)
;
; Inputs      : CARR_ROT = The decimal Carrington rotation number, either whole
;                          or fractional.  For the STEREO spacecraft, this
;                          number should be greater than 2049.3.
;
; Opt. Inputs :	SPACECRAFT = The name or NAIF numeric code of a spacecraft.
;                            See PARSE_SUNSPICE_NAME for more information about
;                            recognized names.  Can also be the name of a solar
;                            system body, e.g. "Earth", "Mars", "Moon", etc.
;                            If not passed, the default is "Earth".
;
; Outputs     :	The result of the function is the date corresponding to the
;               specified Carrington rotation number.
;
; Opt. Outputs:	None.
;
; Keywords    :	PRECISION = The precision in seconds that the result must
;                           match.  Default is 1 second.  Setting the precision
;                           to smaller than 1E-3 is counterproductive.
;
;               TAI     = If set, the result is returned as the TAI time in
;                         seconds since 1-Jan-1958.  Otherwise, the time is
;                         returned in one of the UTC formats.
;
;               Can also pass any keywords accepted by TAI2UTC.
;
; Calls       :	PARSE_SUNSPICE_NAME, UTC2TAI, GET_SUNSPICE_CARR_ROT, TAI2UTC
;
; Common      :	None.
;
; Restrictions:	The Carrington rotation number must be within the range
;               supported by the SPICE ephemeris kernels.
;
;               Not all rotation numbers will correspond to a valid date for
;               all solar system objects.  For example, on 14 March 2010, the
;               Carrington rotation number for Mercury jumps from 2094.0636 to
;               2095.0636 as Mercury passes behind the Sun.  The solar meridian
;               on the far side of the Sun opposite the Sun-Earth line acts in
;               a similar fashion to the International Date Line on Earth when
;               it comes to decimal Carrington rotation numbers.
;
; Side effects:	None.
;
; Prev. Hist. :	None.
;
; History     :	Version 1, 28-Jun-2010, William Thompson, GSFC
;               Version 2, 27-Apr-2016, WTT, renamed from GET_STEREO_CARR_DATE
;               Version 3, 22-Feb-2018, WTT, pass keywords to PARSE_SUNSPICE_NAME
;
; Contact     :	WTHOMPSON
;-
;
function get_sunspice_carr_date, carr_rot, spacecraft, precision=precision, $
                               tai=k_tai, _extra=_extra
on_error, 2
;
if n_params() lt 1 then message, $
  'Syntax: Result = GET_SUNSPICE_CARR_DATE( CARR_ROT  [, SPACECRAFT ] )'
if n_elements(carr_rot)   ne 1 then message, 'CARR_ROT must be a scalar'
if n_elements(spacecraft) gt 1 then message, 'SPACECRAFT must be a scalar'
;
;  Define the default precision as 1 second.
;
if n_elements(precision) eq 0 then precision = 1.0d0
;
;  Determine which spacecraft is being addressed, and get the initial guess
;  based on parameters appropriate for Earth.
;
if n_elements(spacecraft) eq 0 then sc = 'Earth' else $
  sc = parse_sunspice_name(spacecraft, _extra=_extra)
;
param = [68.287402, 0.036661781]
mjd = (carr_rot - param[0]) / param[1]
time = round((mjd - floor(mjd))*86400d3)
utc = {mjd: floor(mjd), time: time}
tai0 = utc2tai(utc)
;
;  Start by searching over one hour.  Don't reiterate more than 100 times.
;
t0 = 0.d0
t1 = 3600d0
niter = 0
while (niter lt 100) and (abs(t1-t0) gt precision) do begin
;
;  Calculate the carrington rotation numbers for the end points.
;
    rot0 = get_sunspice_carr_rot(tai0+t0, sc)
    rot1 = get_sunspice_carr_rot(tai0+t1, sc)
;
;  Linearly extrapolate to the next iteration.
;
    a = (rot1 - rot0) / (t1 - t0)
    b = (rot0*t1 - rot1*t0) / (t1 - t0)
    t = (carr_rot - b) / a
    delta = abs([t0,t1] - t)
    if delta[0] lt delta[1] then t1 = t else t0 = t
;
    niter = niter + 1
endwhile
;
;  Use the midpoint as the final result.
;
tai = tai0 + (t0 + t1) / 2
if keyword_set(k_tai) then return, tai else return, tai2utc(tai, _extra=_extra)
end
