//////////////////////////
// Added by M.Khodosko //
////////////////////////

#include <jni.h>
#include "ovt_object_Sat.h"
#include "satproto.h"
#include <string.h>
#include <math.h>
#include "satellite.h"
#include "aaproto.h"

/***** global variables *****/

FILE   *elefile;

extern struct ELEMENT element;
struct TEMP temp1;

/* from cnstinit.c */
extern int prtflg;
extern double JD;
extern double UT;

extern struct PCONSTANTS pcnsts;
extern struct MCONSTANTS mcnsts;
/**
 * used for temporary saving structure element 
 * if dir = 1 -> save struct element in struct temp
 * if dir = 0 -> restore struct element from struct temp 
 */
int tempr(int dir)
{

  if (dir == 1){
    temp1.xmo = element.xmo;
    temp1.xnodeo = element.xnodeo;
    temp1.omegao = element.omegao;
    temp1.eo = element.eo;
    temp1.xincl = element.xincl;   
    temp1.xno = element.xno;
    temp1.xndt2o = element.xndt2o;
    temp1.xndd6o = element.xndd6o;
    temp1.bstar = element.bstar;
    temp1.epoch = element.epoch;
    temp1.ds50 = element.ds50;   
  }
  if (dir == 0) {
    element.xmo = temp1.xmo;
    element.xnodeo = temp1.xnodeo;
    element.omegao = temp1.omegao;
    element.eo = temp1.eo;
    element.xincl = temp1.xincl;   
    element.xno = temp1.xno;
    element.xndt2o = temp1.xndt2o;
    element.xndd6o =temp1.xndd6o;
    element.bstar =temp1.bstar;
    element.epoch = temp1.epoch;
    element.ds50 = temp1.ds50;   
  }
  return 1;
}
/**The main function.Used for orbit calculation, open tle - file, find JD1
 * recieve OrbitFileName - filename, double array of mjd, size of mjd - SizeOfMjds
 */
int NSat (char *filename,double *mjd,double *gei[],double* vei[],int SizeOfMjds) 
{
    /***** Local variables *****/

    double delo, delt, del1, temp;
    double a1, xnodp, ao, ae;
    double N, D, x;
    int   k, iflag=0,i=0,j=0,ideep;
    int iept=0;
    double oalt=0, oaz=0, ora=0, odec=0;
    double JD1,JD2,JDSTOP=0;

    /***** initialize constants *****/
    prtflg = 0;
    cnstinit ();
    element.epoch = 0;
    JD1 = 0;
    JD2 = 0;
    JD = 0;
    ideep = 0;
    /*** open the element file ***/
    elefile = fopen (filename, "r");
    if (elefile == NULL)
    {
    fprintf (stderr, "Error in opening element file: %s\n", filename);
    return (-1);
    }
    
  for (i=0;i<SizeOfMjds;i++){ 

      JD = mjd[i] + 2433282.50;/*is used to convert JD to MJD */
      if (rdelement() != 0)
    printf("read element bombed!\n");
    
    /***** INPUT CHECK FOR PERIOD VS EPHEMERIS SELECTED *****/
    /***** PERIOD GE 225 MINUTES  IS DEEP SPACE *****/   
     a1 = pow (pcnsts.xke / element.xno, mcnsts.tothrd);
     temp = pcnsts.ck2 * 1.5 *
        (cos (element.xincl) * cos (element.xincl) * 3. - 1.) /
        pow (1. - element.eo * element.eo, 1.5);

     del1 = temp / (a1 * a1);
     ao = a1 * (1. - del1 * (mcnsts.tothrd * .5 + del1 *
          (del1 * 134. / 81. + 1.)));
     delo = temp / (ao * ao);
     xnodp = element.xno / (delo + 1.);
   
    if (mcnsts.twopi / xnodp / pcnsts.xmnpda >= .15625)
    {
      ideep = 1;/*deep space, sdp4 will be used*/
    }
    else ideep = 0;/*near space, sgp4 will be used*/
    iflag = 1;

    if (ideep == 1)
    {
    iept = 2;
    }
    if (ideep == 0)
    {
    iept = 1;
    }
    iflag = 1;
    /////////////

      JD1 = element.epoch;    
        if (JD < JD1)
    {
          printf("epoch = %f\n",element.epoch);
          printf("JD = %f\n",JD);
          printf("ealier than the request\n");
          return(-1);
        }   
      
       while (JD > JD2){            
            tempr(1);       /* searching JD1 - (JD1 < JD < JD2) */
            rdelement();
            JD2 = element.epoch;
            JD1 = JD2;           
        }       
               
         tempr(0); 
         do_orbit (iflag, iept);   
        
          for (j=0;j<3;j++){
           gei[i][j] = Gei[j];
           vei[i][j] = Vei[j]; 
          }
      
        JD = 0;
        fseek(elefile,0,SEEK_SET);/* moving pointer to the begining of file.tle */
  }

     /*if (ideep == 1)
    {
      printf("Sdp4 was used\n");
    }
    if (ideep == 0)
    {
      printf("Sgp4 was used\n");
    }*/

    return 0;
}

/**JNI-  called from Sat.java
  *recieve OrbitFileName(jfilename) 
  *array of mjd(jmjd)
  *size of mjd array(jn) 
  *return array of gei[jn][3](jgei) 
  *array of vei[jn][3](jvei)
*/ 
JNIEXPORT jint JNICALL
Java_ovt_object_Sat_getSatPosJNI(env,obj,jfilename,jmjd,jgei,jvei,jn)
JNIEnv* env;
jobject obj; 
jdoubleArray jmjd;
jstring jfilename;
jobjectArray jgei;
jobjectArray jvei;
const jint jn; 
{
jdouble *mjd;
jint result;
int i,j;
jdoubleArray temp_gei;
jdoubleArray temp_vei;
jdouble** gei = calloc(jn,sizeof(jdouble*)); 
jdouble** vei = calloc(jn,sizeof(jdouble*));

char fname[70];

    const char *filename = (*env)->GetStringUTFChars(env,jfilename,0);
    mjd =(*env)->GetDoubleArrayElements(env,jmjd,0);
    strcpy(fname,filename);   
    for (i=0; i<jn; i++) {
      jdoubleArray temp_gei = (jdoubleArray)(*env)->GetObjectArrayElement(env,jgei,i);/* point temp_gei to the one row of array jgei*/  
      jdoubleArray temp_vei = (jdoubleArray)(*env)->GetObjectArrayElement(env,jvei,i);/* point temp_vei to the one row of array jvei*/         
      gei[i] =(*env)->GetDoubleArrayElements(env,temp_gei, 0);/*point gei to the double array[][] - jgei*/
      vei[i] =(*env)->GetDoubleArrayElements(env,temp_vei, 0);/*point vei to the double array[][] - jvei*/ 
    }
   
  if (NSat(fname,mjd,gei,vei,jn) != 0)
    printf("Error in NSat");
/*       
  (*env)->ReleaseStringUTFChars(env, jfilename, filename); 
  for (i=0; i<jn; i++) {
    (*env)->ReleaseDoubleArrayElements(env, gei_rel[i], gei[i], 0);
    (*env)->ReleaseDoubleArrayElements(env, vei_rel[i], vei[i], 0);  
   }
*/
  free(gei);
  free(vei);
 return;
}
