/*
# This file is part of the Astrometry.net suite.
# Licensed under a 3-clause BSD style license - see LICENSE
*/

#include <math.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>

#include <cairo.h>
#include <cairo-pdf.h>

#include "plotstuff.h"
#include "plotxy.h"
#include "plotimage.h"
#include "xylist.h"
#include "boilerplate.h"
#include "cairoutils.h"
#include "log.h"
#include "errors.h"
#include "fitsioutils.h"
#include "ioutils.h"

#define OPTIONS "hvW:H:n:N:r:s:i:e:x:y:w:S:I:PC:X:Y:b:o:pJ"

static void printHelp(char* progname) {
	BOILERPLATE_HELP_HEADER(stdout);
	printf("\nUsage: %s [options] > output.png\n"
		   "  -i <input-file>   Input file (xylist)\n"
           "  [-o <output-file>] (default: stdout)\n"
           "  [-I <image>   ]   Input image on which plotting will occur; PPM format.\n"
	       "  [-p]: Input image is PNG format, not PPM.\n"
           "  [-P]              Write PPM output instead of PNG.\n"
		   "  [-J]              Write PDF output.\n"
		   "  [-W <width>   ]   Width of output image (default: data-dependent).\n"
		   "  [-H <height>  ]   Height of output image (default: data-dependent).\n"
		   "  [-x <x-offset>]   X offset: position of the bottom-left pixel (default: 1).\n"
		   "  [-y <y-offset>]   Y offset: position of the bottom-left pixel (default: 1).\n"
		   "  [-X <x-column-name>] X column: name of the FITS column.\n"
		   "  [-Y <y-column-name>] Y column: name of the FITS column.\n"
		   "  [-n <first-obj>]  First object to plot (default: 0).\n"
		   "  [-N <num-objs>]   Number of objects to plot (default: all).\n"
		   "  [-r <radius>]     Size of markers to plot (default: 5.0).\n"
		   "  [-w <linewidth>]  Linewidth (default: 1.0).\n"
		   "  [-s <shape>]      Shape of markers (default: circle):",
           progname);
    cairoutils_print_marker_names("\n                 ");
    printf("\n");
    printf("  [-C <color>]      Color to plot in: (default: white)\n");
    cairoutils_print_color_names("\n                 ");
    printf("\n");
    printf("  [-b <color>]      Draw in <color> behind each marker.\n"
           "  [-S <scale-factor>]  Scale xylist entries by this value before plotting.\n"
		   "  [-e <extension>]  FITS extension to read (default 0).\n"
		   "\n");
}


int main(int argc, char *args[]) {
	int argchar;
	char* progname = args[0];

	plot_args_t pargs;
	plotxy_t* xy;
	plotimage_t* img;
	int loglvl = LOG_MSG;

    // log errors to stderr, not stdout.
    errors_log_to(stderr);

	plotstuff_init(&pargs);
	pargs.fout = stdout;
	pargs.outformat = PLOTSTUFF_FORMAT_PNG;

	xy = plotstuff_get_config(&pargs, "xy");
	img = plotstuff_get_config(&pargs, "image");
	assert(xy);
	assert(img);

	plotstuff_set_color(&pargs, "white");
	plotstuff_set_bgcolor(&pargs, "black");
	
	img->format = PLOTSTUFF_FORMAT_PPM;

	while ((argchar = getopt(argc, args, OPTIONS)) != -1)
		switch (argchar) {
		case 'v':
			loglvl++;
			break;
        case 'C':
			plotstuff_set_color(&pargs, optarg);
            break;
        case 'b':
			plotstuff_set_bgcolor(&pargs, "optarg");
            break;
        case 'o':
            pargs.outfn = optarg;
            break;
        case 'X':
			plot_xy_set_xcol(xy, optarg);
            break;
        case 'Y':
			plot_xy_set_ycol(xy, optarg);
            break;
        case 'P':
            pargs.outformat = PLOTSTUFF_FORMAT_PPM;
            break;
		case 'J':
            pargs.outformat = PLOTSTUFF_FORMAT_PDF;
			break;
		case 'p':
			img->format = PLOTSTUFF_FORMAT_PNG;
            break;
        case 'I':
			plot_image_set_filename(img, optarg);
            break;
		case 'S':
			xy->scale = atof(optarg);
			break;
		case 'i':
			plot_xy_set_filename(xy, optarg);
			break;
		case 'x':
			xy->xoff = atof(optarg);
			break;
		case 'y':
			xy->yoff = atof(optarg);
			break;
		case 'W':
			pargs.W = atoi(optarg);
			break;
		case 'H':
			pargs.H = atoi(optarg);
			break;
		case 'n':
			xy->firstobj = atoi(optarg);
			break;
		case 'N':
			xy->nobjs = atoi(optarg);
			break;
		case 'e':
			xy->ext = atoi(optarg);
			break;
		case 'r':
			pargs.markersize = atof(optarg);
			break;
		case 'w':
			pargs.lw = atof(optarg);
			break;
		case 's':
			plotstuff_set_marker(&pargs, optarg);
			break;
		case 'h':
			printHelp(progname);
            exit(0);
		case '?':
		default:
			printHelp(progname);
            exit(-1);
		}

	if (optind != argc) {
		printHelp(progname);
		exit(-1);
	}
	if (!xy->fn) {
		printHelp(progname);
		exit(-1);
	}
	log_init(loglvl);
	log_to(stderr);
	fits_use_error_system();
	if (img->fn) {
		if (plot_image_setsize(&pargs, img)) {
			ERROR("Failed to set plot size from image");
			exit(-1);
		}
		plotstuff_run_command(&pargs, "image");
	} else {
		if (pargs.W == 0 || pargs.H == 0) {
			if (plot_xy_setsize(&pargs, xy)) {
				ERROR("Failed to set plot size from xylist");
				exit(-1);
			}
		}
	}

	plotstuff_run_command(&pargs, "xy");

	plotstuff_output(&pargs);
	plotstuff_free(&pargs);

	return 0;
}
