/*     ----------------------------------------------------------------
*
*                               sgp4io.cpp
*
*    this file contains a function to read two line element sets. while 
*    not formerly part of the sgp4 mathematical theory, it is 
*    required for practical implemenation.
*
*                            companion code for
*               fundamentals of astrodynamics and applications
*                                    2007
*                              by david vallado
*
*       (w) 719-573-2600, email dvallado@agi.com
*
*    current :
*              27 Aug 10  david vallado
*                           fix input format and delete unused variables in twoline2rv
*    changes :
*               3 sep 08  david vallado
*                           add operationmode for afspc (a) or improved (i)
*               9 may 07  david vallado
*                           fix year correction to 57
*              27 mar 07  david vallado
*                           misc fixes to manual inputs
*              14 aug 06  david vallado
*                           original baseline
*       ----------------------------------------------------------------      */

#include "sgp4io.h"

/* -----------------------------------------------------------------------------
*
*                           function twoline2rv
*
*  this function converts the two line element set character string data to
*    variables and initializes the sgp4 variables. several intermediate
varaibles
*    and quantities are determined. note that the result is a structure so
multiple
*    satellites can be processed simultaneously without having to reinitialize.
the
*    verification mode is an important option that permits quick checks of any
*    changes to the underlying technical theory. this option works using a
*    modified tle file in which the start, stop, and delta time values are
*    included at the end of the second line of data. this only works with the
*    verification mode. the catalog mode simply propagates from -1440 to 1440
min
*    from epoch and is useful when performing entire catalog runs.
*
*  author        : david vallado                  719-573-2600    1 mar 2001
*
*  inputs        :
*    longstr1    - first line of the tle
*    longstr2    - second line of the tle
*    typerun     - type of run                    verification 'v', catalog 'c',
*                                                 manual 'm'
*    typeinput   - type of manual input           mfe 'm', epoch 'e', dayofyr
'd'
*    opsmode     - mode of operation afspc or improved 'a', 'i'
*    whichconst  - which set of constants to use  72, 84
*
*  outputs       :
*    satrec      - structure containing all the sgp4 satellite information
*
*  coupling      :
*    getgravconst-
*    days2mdhms  - conversion of days to month, day, hour, minute, second
*    jday        - convert day month year hour minute second into julian date
*    sgp4init    - initialize the sgp4 variables
*
*  references    :
*    norad spacetrack report #3
*    vallado, crawford, hujsak, kelso  2006
  --------------------------------------------------------------------------- */

void twoline2rv(char longstr1[130], char longstr2[130], char typerun,
                char typeinput, char opsmode, gravconsttype whichconst,
                double &startmfe, double &stopmfe, double &deltamin,
                elsetrec &satrec) {
  const double deg2rad = pi / 180.0;         //   0.0174532925199433
  const double xpdotp = 1440.0 / (2.0 * pi); // 229.1831180523293

  double sec, mu, radiusearthkm, tumin, xke, j2, j3, j4, j3oj2;
  double startsec, stopsec, startdayofyr, stopdayofyr, jdstart, jdstop;
  int startyear, stopyear, startmon, stopmon, startday, stopday, starthr,
      stophr, startmin, stopmin;
  int cardnumb, numb, j;
  long revnum = 0, elnum = 0;
  char classification, intldesg[11];
  int year = 0;
  int mon, day, hr, minute, nexp, ibexp;

  getgravconst(whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2);

  satrec.error = 0;

  // set the implied decimal points since doing a formated read
  // fixes for bad input data values (missing, ...)
  for (j = 10; j <= 15; j++)
    if (longstr1[j] == ' ')
      longstr1[j] = '_';

  if (longstr1[44] != ' ')
    longstr1[43] = longstr1[44];
  longstr1[44] = '.';
  if (longstr1[7] == ' ')
    longstr1[7] = 'U';
  if (longstr1[9] == ' ')
    longstr1[9] = '.';
  for (j = 45; j <= 49; j++)
    if (longstr1[j] == ' ')
      longstr1[j] = '0';
  if (longstr1[51] == ' ')
    longstr1[51] = '0';
  if (longstr1[53] != ' ')
    longstr1[52] = longstr1[53];
  longstr1[53] = '.';
  longstr2[25] = '.';
  for (j = 26; j <= 32; j++)
    if (longstr2[j] == ' ')
      longstr2[j] = '0';
  if (longstr1[62] == ' ')
    longstr1[62] = '0';
  if (longstr1[68] == ' ')
    longstr1[68] = '0';

  sscanf(longstr1,
         "%2d %5ld %1c %10s %2d %12lf %11lf %7lf %2d %7lf %2d %2d %6ld ",
         &cardnumb, &satrec.satnum, &classification, intldesg, &satrec.epochyr,
         &satrec.epochdays, &satrec.ndot, &satrec.nddot, &nexp, &satrec.bstar,
         &ibexp, &numb, &elnum);

  if (typerun == 'v') // run for specified times from the file
  {
    if (longstr2[52] == ' ')
      sscanf(longstr2,
             "%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld %lf %lf %lf \n",
             &cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
             &satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum,
             &startmfe, &stopmfe, &deltamin);
    else
      sscanf(longstr2,
             "%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld %lf %lf %lf \n",
             &cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
             &satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum,
             &startmfe, &stopmfe, &deltamin);
  } else // simply run -1 day to +1 day or user input times
  {
    if (longstr2[52] == ' ')
      sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld \n",
             &cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
             &satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
    else
      sscanf(longstr2, "%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld \n",
             &cardnumb, &satrec.satnum, &satrec.inclo, &satrec.nodeo,
             &satrec.ecco, &satrec.argpo, &satrec.mo, &satrec.no, &revnum);
  }

  // ---- find no, ndot, nddot ----
  satrec.no = satrec.no / xpdotp; //* rad/min
  satrec.nddot = satrec.nddot * pow(10.0, nexp);
  satrec.bstar = satrec.bstar * pow(10.0, ibexp);

  // ---- convert to sgp4 units ----
  satrec.a = pow(satrec.no * tumin, (-2.0 / 3.0));
  satrec.ndot = satrec.ndot / (xpdotp * 1440.0); //* ? * minperday
  satrec.nddot = satrec.nddot / (xpdotp * 1440.0 * 1440);

  // ---- find standard orbital elements ----
  satrec.inclo = satrec.inclo * deg2rad;
  satrec.nodeo = satrec.nodeo * deg2rad;
  satrec.argpo = satrec.argpo * deg2rad;
  satrec.mo = satrec.mo * deg2rad;

  satrec.alta = satrec.a * (1.0 + satrec.ecco) - 1.0;
  satrec.altp = satrec.a * (1.0 - satrec.ecco) - 1.0;

  // ----------------------------------------------------------------
  // find sgp4epoch time of element set
  // remember that sgp4 uses units of days from 0 jan 1950 (sgp4epoch)
  // and minutes from the epoch (time)
  // ----------------------------------------------------------------

  // ---------------- temp fix for years from 1957-2056 -------------------
  // --------- correct fix will occur when year is 4-digit in tle ---------
  if (satrec.epochyr < 57)
    year = satrec.epochyr + 2000;
  else
    year = satrec.epochyr + 1900;

  days2mdhms(year, satrec.epochdays, mon, day, hr, minute, sec);
  jday(year, mon, day, hr, minute, sec, satrec.jdsatepoch);

  // ---- input start stop times manually
  if ((typerun != 'v') && (typerun != 'c')) {
    // ------------- enter start/stop ymd hms values --------------------
    if (typeinput == 'e') {
      printf("input start prop year mon day hr min sec \n");
      // make sure there is no space at the end of the format specifiers in
      // scanf!
      scanf("%i %i %i %i %i %lf", &startyear, &startmon, &startday, &starthr,
            &startmin, &startsec);
      fflush(stdin);
      jday(startyear, startmon, startday, starthr, startmin, startsec, jdstart);

      printf("input stop prop year mon day hr min sec \n");
      scanf("%i %i %i %i %i %lf", &stopyear, &stopmon, &stopday, &stophr,
            &stopmin, &stopsec);
      fflush(stdin);
      jday(stopyear, stopmon, stopday, stophr, stopmin, stopsec, jdstop);

      startmfe = (jdstart - satrec.jdsatepoch) * 1440.0;
      stopmfe = (jdstop - satrec.jdsatepoch) * 1440.0;

      printf("input time step in minutes \n");
      scanf("%lf", &deltamin);
    }
    // -------- enter start/stop year and days of year values -----------
    if (typeinput == 'd') {
      printf("input start year dayofyr \n");
      scanf("%i %lf", &startyear, &startdayofyr);
      printf("input stop year dayofyr \n");
      scanf("%i %lf", &stopyear, &stopdayofyr);

      days2mdhms(startyear, startdayofyr, mon, day, hr, minute, sec);
      jday(startyear, mon, day, hr, minute, sec, jdstart);
      days2mdhms(stopyear, stopdayofyr, mon, day, hr, minute, sec);
      jday(stopyear, mon, day, hr, minute, sec, jdstop);

      startmfe = (jdstart - satrec.jdsatepoch) * 1440.0;
      stopmfe = (jdstop - satrec.jdsatepoch) * 1440.0;

      printf("input time step in minutes \n");
      scanf("%lf", &deltamin);
    }
    // ------------------ enter start/stop mfe values -------------------
    if (typeinput == 'm') {
      printf("input start min from epoch \n");
      scanf("%lf", &startmfe);
      printf("input stop min from epoch \n");
      scanf("%lf", &stopmfe);
      printf("input time step in minutes \n");
      scanf("%lf", &deltamin);
    }
  }

  // ------------ perform complete catalog evaluation, -+ 1 day -----------
  if (typerun == 'c') {
    startmfe = -1440.0;
    stopmfe = 1440.0;
    deltamin = 10.0;
  }

  // ---------------- initialize the orbit at sgp4epoch -------------------
  sgp4init(whichconst, opsmode, satrec.satnum, satrec.jdsatepoch - 2433281.5,
           satrec.bstar, satrec.ecco, satrec.argpo, satrec.inclo, satrec.mo,
           satrec.no, satrec.nodeo, satrec);
} // end twoline2rv
