#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "thdrad.h"

/* accuracy of astrometry, 0.001 arcsec */
#define EPS     1.0e-3

#define PI2  ( 2.0 * M_PI )
#define FHRAD  ( M_PI / 12.0 )
#define FHMRAD  ( M_PI / 12.0 / 60.0 )
#define FHSRAD  ( M_PI / 12.0 / 60.0 / 60.0 )
#define FDRAD  ( M_PI / 180.0 )
#define FDMRAD  ( M_PI / 180.0 / 60.0 )
#define FDSRAD  ( M_PI / 180.0 / 60.0 / 60.0 )
#define FRHOUR  ( 12.0 / M_PI )
#define FRHMIN  ( 12.0 * 60.0 / M_PI )
#define FRHSEC  ( 12.0 * 60.0 * 60.0 / M_PI )
#define FRDEG  ( 180.0 / M_PI )
#define FRDMIN  ( 180.0 * 60.0 / M_PI )
#define FRDSEC  ( 180.0 * 60.0 * 60.0 / M_PI )

static void get_num_string2( int num, char *string);

double h60rad( char sign, int h, int m, double s )
{
   double   sig = 1.0 ;
   double   radh ;
   if ( sign == '-' ) {
      sig = - sig ;
   }
   radh = sig * ( ( s / 60.0 + (double) m ) / 60.0 + (double) h ) * FHRAD ;

   radh = fmod( radh, PI2 ) ;
   if ( radh < 0.0 ) {
      radh = radh + PI2 ;
   }

   return radh ;
}

double d60rad( char sign, int d, int m, double s )
{
   double   sig = 1.0 ;
      double   radd ;
         double   eps = 1.0e-8 ;

    if ( sign == '-' ) {
          sig = - sig ;
     }
       radd = sig * ( ( s / 60.0 + (double) m ) / 60.0 + (double) d ) * FDRAD ;
       /*
*    radd = fmod( radd, PI2 ) ;
*       if ( radd < 0.0 ) {
*             radd = radd + PI2 ;
*                }
*                */
          if ( ( radd + PI2 ) < eps ) {
        radd = radd + PI2 ;
   }

     return radd ;
}

void radh60( double radh, char *sign, int *h, int *m, double *s )
{
   double   eps = EPS * 10.0 / 15.0 ;
   /* precision = 0.01 arcsec */
   char   sig = '+' ;
   double   hh, hm, hs ;
   int   ih, im, is ;

   hh = radh * FRHOUR ;
   hh = fmod( hh, 24.0 ) ;
   if ( hh < 0.0 ) {
      hh = hh + 24.0 ;
   }
   ih = (int) hh ;
   hm = ( hh - (int) hh ) * 60.0 ;
   im = (int) hm ;
   hs = ( hm - (int) hm ) * 60.0 ;
   is = (int) ( hs / eps ) ;
   hs = (double) is * eps ;
   if ( ( 60.0 - hs ) < eps ) {
      hs = 0.0 ;
      ++im ;
   }
   if ( im >= 60 ) {
      im = im - 60 ;
      ++ih ;
   }
   if ( ih >= 24 ) {
      ih = ih - 24 ;
   }

   *sign = sig ;
   *h = ih ;
   *m = im ;
   *s = hs ;
}

void radd60( double radd, char *sign, int *d, int *m, double *s )
{
   double   eps = EPS * 10.0 ;
   /* precision = 0.01 arcsec */
   char   sig = '+' ;
   double   dd, dm, ds ;
   int   id, im; //, is;

   if ( radd < 0.0 ) {
      sig = '-' ;
      radd = - radd ;
   }
   dd = radd * FRDEG ;
   dd = fmod( dd, 360.0 ) ;
   if ( dd < 0.0 ) {
      dd = dd + 360.0 ;
   }
   id = (int) dd ;
   dm = ( dd - (int) dd ) * 60.0 ;
   im = (int) dm ;
   ds = ( dm - (int) dm ) * 60.0 ;
   if ( ( 60.0 - ds ) < eps ) {
      ds = 0.0 ;
      ++im ;
   }
   if ( im >= 60 ) {
      im = im - 60 ;
      ++id ;
   }
   if ( id >= 360 ) {
      id = id - 360 ;
   }
   if ( fabs( radd ) < eps * FDSRAD && ds < eps ) {
      sig = '+' ;
   }

   *sign = sig ;
   *d = id ;
   *m = im ;
   *s = ds ;
}

/* transformation from RA and Dec (hh:dd:ss.s (+/-)dd:mm:ss.s) *
 *  *   to alpha and delta in radian                              */
void alpha_delta(char RA[], char Dec[], double *alpha, double *delta){
   int RA_h, RA_m, Dec_d, Dec_m;
   double RA_s, Dec_s;
   char sign;
   sscanf(RA,"%d:%d:%lf",&RA_h,&RA_m,&RA_s);
   sign='+';
   *alpha=h60rad( sign, RA_h, RA_m, RA_s );
   sign=Dec[0];
   sscanf(Dec+1,"%d:%d:%lf",&Dec_d,&Dec_m,&Dec_s);
   *delta=d60rad( sign, Dec_d, Dec_m, Dec_s );
   return;
}

/* transformation from alpha and delta in radian    *
 *   to RA and Dec (hh:dd:ss.s (+/-)dd:mm:ss.s)     */
void RA_Dec(double alpha, double delta, char *RA, char *Dec){
   int RA_h, RA_m, Dec_d, Dec_m;
   double RA_s, Dec_s;
   char sign;
   char sRA_h[5], sRA_m[5], sRA_s[10];
   char sDec_d[5], sDec_m[5], sDec_s[10];
   radh60( alpha, &sign, &RA_h, &RA_m, &RA_s );
   get_num_string2(RA_h, sRA_h);
   get_num_string2(RA_m, sRA_m);
   if(RA_s<10) sprintf(sRA_s,"0%.2f",RA_s);
   else sprintf(sRA_s,"%.2f",RA_s);
   sprintf(RA,"%s:%s:%s",sRA_h,sRA_m,sRA_s);
   radd60( delta, &sign, &Dec_d, &Dec_m, &Dec_s );
   get_num_string2(Dec_d, sDec_d);
   get_num_string2(Dec_m, sDec_m);
   if(Dec_s<10) sprintf(sDec_s,"0%.1f",Dec_s);
   else sprintf(sDec_s,"%.1f",Dec_s);
   sprintf(Dec,"%c%s:%s:%s",sign,sDec_d,sDec_m,sDec_s);
}

static void get_num_string2( int num, char *string){
   int i;
   sprintf(string,"%2d",num);
   for(i=0;i<2;i++) if(string[i]==' ') string[i]='0';
}

Boolean check_alpha_delta(double alpha, double delta){
   if(fabs(delta)>M_PI/2||alpha<0||alpha>2*M_PI){
      fprintf(stderr,"!!! alpha=%g delta=%g out of range !!!\n",alpha,delta);
      return FALSE;
   }
   return TRUE;
}

#undef EPS

