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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <math.h>

#include "tycho2-fits.h"
#include "starutil.h"
#include "mathutil.h"
#include "an-endian.h"

#define OPTIONS "ho:"

static void print_help(char* progname) {
    printf("usage:\n"
           "  %s -o <output-filename>\n"
           "  <input-file> [<input-file> ...]\n\n"
           "Input files must be Tycho-2 FITS files.\n"
           "Output file will be in Stellarium format.\n\n",
           progname);
}

static int write_32(FILE* fout, void* p) {
    if (fwrite(p, 1, 4, fout) != 4) {
        fprintf(stderr, "Failed to write 32-bit quantity: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}
static int write_16(FILE* fout, void* p) {
    if (fwrite(p, 1, 2, fout) != 2) {
        fprintf(stderr, "Failed to write 16-bit quantity: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}
static int write_8(FILE* fout, void* p) {
    if (fwrite(p, 1, 1, fout) != 1) {
        fprintf(stderr, "Failed to write 8-bit quantity: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}


int main(int argc, char** args) {
    char* outfn = NULL;
    int c;
    int startoptind;
    FILE* fout;

    while ((c = getopt(argc, args, OPTIONS)) != -1) {
        switch (c) {
        case '?':
        case 'h':
            print_help(args[0]);
            exit(0);
        case 'o':
            outfn = optarg;
            break;
        }
    }

    if (!outfn || (optind == argc)) {
        print_help(args[0]);
        exit(-1);
    }

    fout = fopen(outfn, "wb");
    if (!fout) {
        fprintf(stderr, "Failed to open output file: %s\n", strerror(errno));
        exit(-1);
    }

    //qfits_err_register(qfits_dispfn);
    //qfits_err_statset(1);

    startoptind = optind;
    for (; optind<argc; optind++) {
        tycho2_fits* tycho = NULL;
        qfits_header* hdr;
        anbool is_tycho = FALSE;
        int i, N;
        uint32_t ui;
        char* infn;

        infn = args[optind];
        printf("Opening catalog file %s...\n", infn);
        hdr = qfits_header_read(infn);
        if (!hdr) {
            fprintf(stderr, "Couldn't read FITS header in file %s.\n", infn);
            exit(-1);
        }
        is_tycho = qfits_header_getboolean(hdr, "TYCHO_2", 0);
        if (!is_tycho) {
            fprintf(stderr, "File %s doesn't have TYCHO_2 FITS header.  Skipping file.\n", infn);
            continue;
        }
        tycho = tycho2_fits_open(infn);
        if (!tycho) {
            fprintf(stderr, "Couldn't open Tycho-2 catalog: %s\n", infn);
            exit(-1);
        }

        N = tycho2_fits_count_entries(tycho);

        fprintf(stderr, "Reading %i entries...\n", N);

        // Stellarium header: how many stars in the catalog
        // (32-bit uint).
        ui = u32_htole(N);
        if (write_32(fout, &ui)) exit(-1);

        for (i=0; i<N; i++) {
            tycho2_entry* e;
            float ra, dec, distance, mag;
            int nmag;
            int tmpmag;
            uint16_t imag;
            uint8_t type;

            e = tycho2_fits_read_entry(tycho);
            if (!e) {
                fprintf(stderr, "Failed to read a Tycho-2 entry.\n");
                exit(-1);
            }

            ra = e->RA;
            dec = e->DEC;
            // just avg the available magnitudes.
            nmag = 0;
            mag = 0.0;
            // in Tycho-2, mag 0.0 means it's unavailable.
            if (e->mag_BT != 0.0) {
                mag += e->mag_BT;
                nmag++;
            }
            if (e->mag_VT != 0.0) {
                mag += e->mag_VT;
                nmag++;
            }
            if (e->mag_HP != 0.0) {
                mag += e->mag_HP;
                nmag++;
            }
            if (nmag)
                mag /= (float)nmag;

            // ra: degrees -> hours
            ra *= 24.0 / 360.0;
            // dec: degrees -> degrees
            // imag: 256 * mag - 5

            // distance info isn't in Tycho-2.
            distance = 1.0;

            tmpmag = (int)rint(256.0 * mag);
            if (tmpmag < 0)
                tmpmag += 0x10000;
            imag = tmpmag;

            //type = 12; // "other"
            type = 0; // "other"

            v32_htole(&ra);
            v32_htole(&dec);
            v16_htole(&imag);
            v32_htole(&distance);

            write_32(fout, &ra);
            write_32(fout, &dec);
            write_16(fout, &imag);
            write_8 (fout, &type);
            write_32(fout, &distance);

        }
        tycho2_fits_close(tycho);
    }

    if (fclose(fout)) {
        fprintf(stderr, "Failed to close output file: %s\n", strerror(errno));
        exit(-1);
    }

    return 0;
}
