// sattool - visual satellite tracking and prediction tool.
// Copyright 2000 Tom Rothamel <tom-idbg@onegeek.org>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  

#ifndef SATTOOL_H
#define SATTOOL_H

extern "C" {
#include "sgp.h"
}

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
#include <math.h>

// Error is used when a function is unable to even attempt to complete.
#define error(args...) fprintf(stderr, "sattool error: " args)
// Warning is used when the function may produce unexpected results, but
// it can still proceed to completion.
#define warning(args...) fprintf(stderr, "sattool warning: " args)

class Object;
class Sat;
class Sgp4Sat;

// A Thing is the base class for all the satclasses.
class Thing {
 public:
	int uses;
	Object *_object;
	Sat *_sat;
	double _time;
	
	virtual void write(FILE *, int);
	virtual ~Thing();

	Thing();
};

// A ListElement is one Element of a list.
struct ListElement {
	ListElement *next;
	ListElement *prev;
	
	Thing *data;
};

// A List is a linked list of Things. It can be created and walked.
// Please note that destroying the List will not destroy all the Things
// that are part of it.
class List {
 public:
	ListElement *first;
	ListElement *last;
	ListElement *cur;

	int count;

	void add(Thing *);
	void reset();
	Thing *next();
	Thing *prev();

	List();
	~List();
};

// This is the structure created by ParseGlobalOptions, containing
// member variables corresponding to all of the standard command line
// options. 
struct Options {
	char *infile; 
	char *outfile;

	int tle; 
	int quiet;
	int visual;
	int debug;
};




/////////////////////////// Physical Constants ///////////////////////////

#define R (6378.135) /* Radius of earth at the equator, km. */
#define SECDAY (1.0/86400.0) /* 1 Second as a fraction of a day. */
#define RADEG (180.0/M_PI)
#define DEGRAD (M_PI/180.0)

/////////////////////////// Satclass Classes /////////////////////////////

// A Position is a point in the Earth Centered Inertial coordinate
// system. It can also contain optional orientation. 
class Position : public Thing {
public:
	double t;
	double x[3];
	double dx[3];

	double coslat;
	double sinlat;

	double costheta;
	double sintheta;

};

// A LLA is a latitude, longitude, and altitude WRT the Earth's
// surface.
class LLA : public Thing {
public:
	double lat;
	double lon;
	double alt;

	LLA(Position *); // Calculate based on an object's position
};

// An Object is something that can calculate a Position at a given
// time.
class Object : public Thing {
public:
	char *name;
	
	virtual Position *calcpos(double, Position *) = 0;
	virtual Position *calc1(double);
	Object();
};

// An Encounter details the relative positions of two objects at
// a given point in time. At least one of the objects (the site) must
// also generate orientation information.
class Encounter : public Thing {
public:
	Object *obj; 
	Position *objp;
	Object *site; 
			
	Position *sitep;

	Position *relp; 
	Position *rotp; 
	                
	double t; 
	
	double elevation; 

	// The following are only calculated when calcmore is called.
	
	double azimuth; 
	double range; 
	double ra; 
	double dec;
	
	double calc(Object *, Object *, double);
	void calcmore();

	Encounter();
	Encounter(Object *, Object *, double);

	~Encounter();
};

// A Sat is an object representing an artificial satellite. It has
// both a norad and an international designation, as well as a way
// of computing it's mean motion.
class Sat : public Object {
public:
	int norad;
	char *desig;
	double epoch;

	virtual int hasmag();
	virtual double calcmag(Encounter *e);
	
	virtual double mm(double) = 0;
	Sat();
};

// A Sgp4Sat is a satellite in earth orbit that can be modelled using
// the Sgp4 algorithm. It's what's described in TLE files.
class Sgp4Sat : public Sat {
public:
	SAT *s;
	char sgpname[30];
	double ct;

	char *line[3];
	
	Position *calcpos(double, Position *);
	double mm(double);
	void write(FILE *, int);
	int hasmag();
	double calcmag(Encounter *e);
	

	
	Sgp4Sat(char *, char *, char *);
	~Sgp4Sat();
};

// An EarthSite is an object that's fixed to the Earth's surface.
class EarthSite : public Object {
public:
        double sinlat;
        double coslat;
        double lonr;
        double alt;

	double storelat;
	double storelon;
	
	Position *calcpos(double, Position *);
	void write(FILE *, int);
	
        EarthSite(char *, double, double, double);
        ~EarthSite();
};

// A Pass describes when a sat is above the horizon WRT a site.
class Pass : public Thing {
 public:
	Sat *sat;
	Object *site;

	// The maximum elevation reached.
	double maxel; 

	// The times of rise, max, and set.
	double min0; 
	double max; 
	double min1; 

	// Time and minimum magnitudes for visual predictions.
	double mmt;
	double minmag;
	
	void write(FILE *, int);
	void visual(double);
	
	Pass();
	Pass(Sat *, Object *, double, double, double, double,
	     double, double);
	~Pass();
};

///////////////////////////// Functions ///////////////////////////////////

// date_parser.yy
time_t parse_date(char *);
double parse_sgp_date(char *);

// list.cc
List *SortList(List *, int(*)(Thing **, Thing **));	

// object.cc
void lock(Thing *);
void unlock(Thing *);
Sat *getSat(Thing *);
Sgp4Sat *getSgp4Sat(Thing *);
Object *getObject(Thing *);
Pass *getPass(Thing *);
Encounter *getEncounter(Thing *);

// options.cc
Object *GetSite();
Options *ParseGlobalOptions(int, char **, int *);
List *ReadInput(Options *);
void WriteOutput(Options *, List *);
FILE *OutputFile(Options *);

// parser.yy
int yyparse(void *);
extern FILE *yyin;

// pass.cc
void PredictSat(List *, Sat *, Object *,
		double, double, double, double);

// passes.cc
void print_encounter(FILE *, Pass *, char *, double);

// sgp4sat.cc
List *ReadTLEFile(FILE *);

// sun.cc
int isLit(Position *);
double SiteSatSun(Position *, Position *);
double SunElevation(Object *, double);

// utils.cc
char *strdup(char *);
char *stradd(char *, char *);
void pad(FILE *, int);
void chomp(char *);
void strfsgptime(char *, int, char *, double);
char *CompassDir(double);


////////////////////////////// Commands ///////////////////////////////////

int cat(int, char **);
int writetle(int, char **);
int filter(int, char **);
int marker(int, char **);
int datetest(int, char **);
int live(int, char **);
int predict(int, char **);
int passes(int, char **);
int step(int, char **);
int summary(int, char **);

#endif
