#if defined(__MINGW32__) || defined(__MINGW64__)
#define MSWIN32
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <math.h>

#include "fft.h"

typedef unsigned int u32;
typedef int s32;
typedef float f32;

#define DIR_MAX_COUNT 100000

/************************************************************/

struct cfunc
	{
	char *option;
	int (*func)(char *, char *, int);
	};

#include "version.h"
#include "globals.h"

#define TRUE 1
#define FALSE 0

// Parameters for use with -renumber commandline switch
#define QRENUMBER_FIRST 1
#define QRENUMBER_LAST 2

#define POPFILTER_BEFORE 1
#define POPFILTER_AFTER  2

#define SMOOTHING_BEFORE 1
#define SMOOTHING_AFTER 2

// Valid values for Image->type;
#define IMG_PPM		1
#define IMG_BMP		2
#define IMG_FIT		3
#define IMG_FIT32U	4	// 32 bit unsigned int, depth = 32
#define IMG_FIT32F	4	// 32 bit floating point, depth = 32

// StreamFilter types
#define AVG		1
#define AVG_LOW		2
#define AVG_HIGH	3
#define LOW		4
#define MEDIAN		5
#define HIGH		6
#define MAX_POP		7

#define HISTO		1
#define GRADIENT	2
#define BR_THRESH	3

// A "practical" maximum 32 bit value. Assume that brighter pixels are artifacts
#define UMAX32s ((u32)65535 * (u32)65530)

// unsigned and signed maximum values
#define UMAX32 0xffffffff
#define SMAX32 0x7fffffff

// flags for ArchiveLoadNextImage
#define ARCHIVE_LOAD 1
#define ARCHIVE_SKIP 2
#define ARCHIVE_COMPRESSED 4

#define FITS_LOAD 1
#define FITS_SKIP 2
#define FITS_COMPRESSED 4

#define BAYER_GBG 1
#define BAYER_RGR 2
#define BAYER_BGB 3
#define BAYER_GRG 4

// Entries for DBF (DetectBrokenFrames).
// Planet means we can be more strict in locating broken frames
// by watching for sudden movement of the centre of brightness
#define DBF_PLANET 1
#define DBF_LUNAR 2

// Modes for locatig the centre of an image
#define CENTRE_BARYCENTRE	1
#define CENTRE_LEFT		2
#define CENTRE_RIGHT		3

#define IMAGECOUNT_MAX 999999

/*
 * BMP file format header
 */

/*
 * Note that we ignore the last 5 fields 
 */

typedef struct
	{
	int filesz;	/* size of BMP file */
	short r1;	/* reserved - must be 0 */
	short r2;	/* reserved - must be 0 */
	int offset;	/* offset to image data */
	int size;	/* size of remaining header (must be 40) */
	int width;	/* image width in pixels */
	int height;	/* image height in pixels */
	short planes;	/* must be 1 */
	short bitcount;	/* bits per pixel - 1,2,4,8,16,24,32 */
	int compression;/* must be 0 for uncompressed image */
	int sizeimage;	/* image size - may be 0 for uncompressed image */
	int xppm;	/* X pixels per metre (ignore) */
	int yppm;	/* Y pixels per metre (ignore) */
	int cmapentries;/* Number of colourmap entries */
	int clrimportant; /* number of important colours */
	} bmp_header;

struct Region
	{
	int x1,y1;
	int x2,y2;
	};

struct QRegion
	{
	struct Region r;
	int histo_low;
	int histo_high;
	};

struct morph_point
	{
	int active;		// is this point in use?
	int x,y;		// Location of control point (centre)
	int w,h;		// width and height of control area
	int x_offset;		// translation
	int y_offset;		// translation
	double scale;		// lensing
	};

struct image_quality
        {
        int bucket;  // 0..6
        char *newname;
        double val;
        };

struct merge_info {
	double avg;
	};

struct Image
        {
        char *src_fname;	// Name of source file
	char *dst_fname;	// Name of destination file
	int type;		// IMG_*
        unsigned char *data;	// Image data bytes from file
	void *info;		// Image-specific info
        int width, height;	// Width, Height, Depth of source image
	int sub_x,sub_y;	// centre of interest
	int dst_width;		// Width of destination image
	int dst_height;		// Height of destination image
        int depth;
	double tm_sec;		// floating point timestamp in seconds
	unsigned long long tm_tsc; // timestamp in cpu ticks

	struct merge_info m;	// Info for merging
	struct Region cutout;	// Region to cut from source image
	struct image_quality *q;	// Image quality info
	int histo_warning;	// Set to 1 if image contains overbright pixels
        };

// Struct for FITS image type
struct fits_info
	{
	u32 bzero;
	double bscale;
	unsigned char *header;	// Primary header from source
	};

struct bmp_info
	{
	int cmap_entries;
	unsigned char *cmap;
	};

struct ppm_info
	{
	char ppm_type[3];	// "P6" etc
	int maxval;
	};

struct weight
        {
        short active;                   // set to 1 when in use
        struct morph_point *ptr;        // control point
        double wgt;                     // fractional weight (0..1)
        };

void Usage(void);
int isDirectory(char *);
int Print(char *fmt,...);
int smooth_image(struct Image *img,int scale);
int smooth_image_16(unsigned char *data,int width,int height,int scale);
int scale_image(struct Image *img, int n);
int pop_filter(struct Image *);

// fileio.c
int load_image_header(FILE *in, struct Image *img);
int ReadByte(FILE *in);
int Fread(unsigned char *buffer, int size, int count, FILE *in);
struct Image * CreateImage(void);
struct Image * ConvertImage(struct Image *src, int type, int depth);
int SetCutoutRegion(struct Image *img, int x1, int y1, int x2, int y2);
struct Image * CreateFitsImage(char *dst_fname, int width, int height, int depth,
                unsigned char *data, u32 bzero, double bscale);
struct Image * LoadImage(char *src_fname, char *dst_fname);
int write_image_header(FILE *out,struct Image *img);
int write_image_data(FILE *out,struct Image *img);
int WriteImage(struct Image *img);
int InvertImage(struct Image *);
int MirrorImage(struct Image *);
struct Image * ArchiveLoadNextImage(FILE *in, int *err, int flags);
FILE * OpenArchive(char *name);
int ExtractArchive(char *archive_name, char *dstdir);
struct Image *ConvertToType(struct Image *, int newtype, int newdepth);
int ArchiveNextFilename(char *this, char *next);

// align.c
void Mkdir(char *dirname);
int Align(char *);
int SubtractDarkFrame(struct Image *);

// process.c
int FindCentre(struct Image *img, int *x_avg, int *y_avg);
int CalculateCutout(struct Image *img);
int CutOut(struct Image *img);
int ApplyGamma(struct Image *img, double gamma);
int ProcessDir(char *dir);
int process(struct Image *img);
double input_filter(struct Image *img);
int Clip(int w, int h, int *x1, int *y1, int *x2, int *y2);

// stack.c
int stack_frame(struct Image *img);
int write_stack_file(char *fname);
int merge_data(char *mfile, struct Image *img);

// quality.c
void QualitySort(void);
void QAssociate(char *fname, double quality);
void WriteQFile(char *fname);
int SubSample(unsigned char *ptr, int img_wid, int bpp, int x_size, int y_size);
double QualityEstimate(struct Image *img);
void Qrenumber(int);

// debayer.c
struct Image * DeBayer(struct Image *img, int p);
int FixBayer8(struct Image *img);

// morph.c
int smooth_image3x3(struct Image *img);
int translate_image(struct Image *img, int dx, int dy);
int morph_image(struct Image *img, int level);

// subsample.c
struct Image ** GenerateSubSampledImages(struct Image *img, struct Region *r, int *xsizes, int *ysizes, int depth, int count);
int Test_Subsample(struct Image *img);

// util.h
char * VStrdup(char *);
void * Malloc(int nbytes);
void * ZeroMalloc(int nbytes);
char * TypeName(int type);
double d_Random(void);
int Random(int);
int Srandom(void);
FILE * OpenLogfile(char *fname, char *mode);
int AllowWrite(char *fname);
int isSupportedFile(char *fname);
int Usleep(int);
void ShowImage(struct Image *img);

// tables.h
double * create_weight_buffer_decrease_lr(int w, int h);
double * create_weight_buffer_increase_lr(int w, int h);
double * create_weight_buffer_decrease_ud(int w, int h);
double * create_weight_buffer_increase_ud(int w, int h);
double * create_weight_buffer_decrease_tl(int w, int h);
double * create_weight_buffer_decrease_tr(int w, int h);
double * create_weight_buffer_decrease_bl(int w, int h);
double * create_weight_buffer_decrease_br(int w, int h);
int map_control_points(struct morph_point *m, int npoints, struct Image *img);
int draw_point(struct Image *img, int x, int y, unsigned int val);

//streamfilter.c
void init_streamfilter(void);
struct Image *CloneImage(struct Image *);
int do_StreamFilter(struct Image *img);

//rotate.c
int RotateImage(struct Image *img, double angle);

// fftutil.c
int fft_filter(struct Image *img, double lpf_r1, double lpf_r2, double lpf_p);
int fft_register_pad(struct Image *ref, struct Image *img, double lpf_r1, double lpf_r2, double lpf_p, int region, int *dx, int *dy);
int fft_register(struct Image *ref, struct Image *img, double lpf_r1, double lpf_r2, double lpf_p, int region, int *dx, int *dy);

// hotpixel.c
int do_DetectHotpixels(struct Image *img);
int WriteHotPixelFile(char *fname);

// font.c
int DrawString(struct Image *img, int y, int x, char *str);

//ftacompress.c
int _ftz_decode_frame(struct Image *img, char *buffer,int zbytes);

// switches.c
int LoadConfigFile(char *fname, char **params, char **vals);
int SetVariable(char *str);
int Interact(void);

