package orbit;

/**
 * Represents the NASA 2-line orbital element.  As of 07 Jan 2003:
 *
 * ISS
 * 1 25544U 98067A   03007.53073344  .00041100  00000-0  34010-3 0  9019
 * 2 25544  51.6346 107.2569 0004536   6.6073 353.5141 15.58656572 35940
 *
 * (from http://spaceflight.nasa.gov/realdata/sightings/SSapplications/Post/JavaSSOP/orbit/ISS/SVPOST.html)
 *
 * ISS (ZARYA)
 * 1 25544U 98067A   03007.15863095  .00022159  00000-0  28892-3 0  5534
 * 2 25544  51.6345 109.1211 0004923   6.2534  64.4750 15.58618678235921
 *
 * (from http://celestrak.com/NORAD/elements/stations.txt - this doesn't look exactly right; there's no space in the
 * final field of line 2!)
 *
 * <p>Title: ISS Transit</p>
 * <p>Description: Predict transits of the ISS across the moon and sun</p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: J2EE Consultants</p>
 * @author Thomas Fly
 * @version 1.0
 */

public class TwoLineElement {

  final static int MINUTES_PER_DAY = 1440;

/*  First line:
*/
  final String satelliteNumber;
  final String classification;

  final String launchYear;
  final String launchNumber;
  final String pieceOfLaunchVehicle;

  final String epochYear;
  final String epoch;

  final String firstDerivativeMeanMotion;
  final String secondDerivativeMeanMotion;

  final double dragCoefficient;
  final String ephemerisType;
  final String elementNumber;
  final String checksum_1;

/*  Second line:
*/
  final String satelliteNumber_2;
  final double orbitInclination;
  final double rightAscensionAscendingNode;
  final double orbitEccentricity;
  final double orbitPerigee;
  final double meanAnomaly;
  final double meanMotion;
  final String revolutionNumberAtEpoch;
  final String checksum_2;

  public TwoLineElement(String[] twoLine) {

/*  First line:
 25544U 98067A   03007.53073344  .00041100  00000-0  34010-3 0  9019  ... or,
 25544U 98067A   03007.15863095  .00022159  00000-0  28892-3 0  5534

Butt-ugly Pascal translated from even-more butt-ugly FORTRAN:

{* Decode Card 1 *}
  catnr    := Copy(abuf[1],3,5);
  epoch    := Real_Value(abuf[1],19,14);
  julian_epoch := Julian_Date_of_Epoch(epoch);
  xndt2o   := Real_Value(abuf[1],34,10);
  xndd6o   := Real_Value(abuf[1],45,6)*1E-5;
  iexp     := Integer_Value(abuf[1],51,2);
  bstar    := Real_Value(abuf[1],54,6)*1E-5;
  ibexp    := Integer_Value(abuf[1],60,2);
  elset    := ThreeDigit(Integer_Value(abuf[1],66,3));
*/
    // catnr    := Copy(abuf[1],3,5)
    satelliteNumber = twoLine[0].substring(2, 7);
    classification = twoLine[0].substring(7, 8);

    launchYear = twoLine[0].substring(9, 11);
    launchNumber = twoLine[0].substring(11, 14);
    pieceOfLaunchVehicle = twoLine[0].substring(14, 17);

    // epoch := Real_Value(abuf[1],19,14)
    epochYear = twoLine[0].substring(18, 20);
    epoch = twoLine[0].substring(20, 32);

    // xndt2o := Real_Value(abuf[1],34,10)
    firstDerivativeMeanMotion = twoLine[0].substring(33, 43);

    // xndd6o := Real_Value(abuf[1],45,6)*1E-5
    // iexp := Integer_Value(abuf[1],51,2)
    secondDerivativeMeanMotion = twoLine[0].substring(44, 52);

    // bstar := Real_Value(abuf[1],54,6)*1E-5
    // ibexp := Integer_Value(abuf[1],60,2)
    dragCoefficient = new Double(twoLine[0].substring(53, 59)).doubleValue() * 1e-5 *
                      new Double("1e" + twoLine[0].substring(59, 61)).doubleValue();

    ephemerisType = twoLine[0].substring(62, 63);
// HUH???  elset := ThreeDigit(Integer_Value(abuf[1],66,3))
    elementNumber = twoLine[0].substring(64, 68);
    checksum_1 = twoLine[0].substring(68, 69);

/*  Second line:
 25544  51.6346 107.2569 0004536   6.6073 353.5141 15.58656572 35940  ... or,
 25544  51.6345 109.1211 0004923   6.2534  64.4750 15.58618678235921

More butt-ugly code:

{* Decode Card 2 *}
  xincl    := Real_Value(abuf[2],9,8);
  xnodeo   := Real_Value(abuf[2],18,8);
  eo       := Real_Value(abuf[2],27,7)*1E-7;
  omegao   := Real_Value(abuf[2],35,8);
  xmo      := Real_Value(abuf[2],44,8);
  xno      := Real_Value(abuf[2],53,11);
*/
    satelliteNumber_2 = twoLine[1].substring(2, 7);
    // xincl    := Real_Value(abuf[2],9,8)
    orbitInclination = new Double(twoLine[1].substring(8, 16)).doubleValue() * Math.PI / 180;
    // xnodeo   := Real_Value(abuf[2],18,8)
    rightAscensionAscendingNode = new Double(twoLine[1].substring(17, 25)).doubleValue() * Math.PI / 180;
    // eo       := Real_Value(abuf[2],27,7)*1E-7
    orbitEccentricity = new Double(twoLine[1].substring(26, 33)).doubleValue() * 1e-7;
    // omegao   := Real_Value(abuf[2],35,8)
    orbitPerigee = new Double(twoLine[1].substring(34, 42)).doubleValue() * Math.PI / 180;
    // xmo      := Real_Value(abuf[2],44,8)
    meanAnomaly = new Double(twoLine[1].substring(43, 51)).doubleValue() * Math.PI / 180;
    // xno      := Real_Value(abuf[2],53,11)
    meanMotion = new Double(twoLine[1].substring(52, 63)).doubleValue() * 2 * Math.PI / MINUTES_PER_DAY;

    revolutionNumberAtEpoch = twoLine[1].substring(64, 68);
    checksum_2 = twoLine[1].substring(68, 69);
  }
}