#include "SaoFile.h"

#include <iostream.h>
#include <string.h>

#include "slamac.h"

#include "File.h"

#define FALSE 0
#define TRUE  1

ClassImp(SaoFile);

static int lt(sort_t *t1, sort_t *t2)
{
    // t1->ra < t2->ra
    if (t1->ra < t2->ra)
        return 1;

    // t1->ra > t2->ra
    if (t1->ra > t2->ra)
        return 0;

    // t1->ra == t2->ra
    if (t1->dec < t2->dec)
        return 1;
    else
        return 0;
}


static void rekMergesort(sort_t **a, int length, int l, int r)
{
    // a recursive merge sort algorithm
    if ( r <= l )
        return;

    sort_t **b = new sort_t*[length];

    int m = (r+l)/2;

    rekMergesort(a, length, l, m);

    rekMergesort(a, length, m+1, r);

    int i;
    for (i=m+1; i>l; i--)
        b[i-1]=a[i-1];

    int j;
    for (j=m; j<r; j++)
        b[r+m-j]=a[j+1];

    int k;
    for (k=l; k<=r; k++)
    {
        if (lt( b[i],b[j]) )
            a[k]=b[i++];
        else
            a[k]=b[j--];
    }

    delete b;
}

SaoFile::SaoFile(const char *name)
{
    file = new File(name, "r");

    if (!*file)
        exit(0);

    compressed = !strcasecmp(name+strlen(name)-4, ".cmp");

    fEntries = file->Size()/(compressed?70-20:205);

    cout << "Opening" << (compressed?" compressed":"") << " catalog '" << name << "'"
        << " with " << fEntries << " entries" << endl;

    delFlag = ' ';
}

SaoFile::~SaoFile()
{
    delete file;
}

int SaoFile::GetEntryNr() const
{
    return file->Tell()/(compressed?70-20:205);
}

int SaoFile::GetEntry(const int i)
{
    file->Seek(i*(compressed?70-20:205));
    return GetNextEntry();
}

void SaoFile::Reset() const
{
    file->Seek(0);
}

int SaoFile::GetNextEntry()
{
    if (file->Eof())
        return FALSE;

    SAO = file->Geti(6);
    if (!compressed)
    {
        delFlag = file->Getc();
        file->Skip(77-8);
    }
    Pmag      = file->Getf(4);
    Vmag      = file->Getf(4);
    if (!compressed)
        file->Skip(161/*151*/-85);
    /*
     RA2000h   = file->geti(2);
     RA2000m   = file->geti(2);
     RA2000s   = file->getf(6);
     */
    pmRA2000  = file->Getf(7);
    if (!compressed)
        file->Skip(178-168);
    /*
     DE2000sgn = file->getc();
     DE2000d   = file->geti(2);
     DE2000m   = file->geti(2);
     DE2000s   = file->getf(5);
     */
    pmDE2000  = file->Getf(6);
    RA2000rad = file->Getf(10);
    DE2000rad = file->Getf(11);
    file->Newline();

    sprintf(data, "%6i%4.1f%4.1f"/*"%2i%2i%6.3f"*/"%7.4f"/*"%c%2i%2i%5.2f"*/"%6.3f%10.8f%11.8f\n",
            Nr(), MagP(), MagV(), /*RaH(), RaM(), RaS(),*/ RaPm(),
            /*DecSgn(), DecD(), DecM(), DecS(),*/ DecPm(), Ra(), Dec());

    return !file->Eof();
}

void SaoFile::Print() const
{
    cout << SAO << " " << delFlag << " " << Pmag << " " << Vmag << " "
        << /*RA2000h << "h" << RA2000m << "m" << RA2000s << "s " << */pmRA2000 << " "
        << /*DE2000sgn << DE2000d << "d" << DE2000m << "m" << DE2000s << "s " << */pmDE2000 << " Ra:"
        << RA2000rad << " Dec:" << DE2000rad << endl;
}

void SaoFile::Compress()
{
    FILE *f = fopen("sao.cmp", "w");

    cout << endl << " Compressing catalog..." << flush;

    const int entries = GetNrOfEntries();
    const int step    = entries/360;

    for (int i=0; i<entries; i++)
    {
        GetNextEntry();

        if (!DelFlag())
            fprintf(f, String());

        if (i%step==0)
            cout << "." << flush;
    }
    cout << "done." << endl;

    fclose(f);
}

void SaoFile::Sort()
{
    cout << endl << "Reading coordinates..." << flush;

    const int entries=GetNrOfEntries();

    sort_t **srt = new sort_t*[entries];
    for (int i=0; i<entries; i++)
        srt[i] = new sort_t;

    int counter=0;
    const int step = entries/360;
    while(GetNextEntry())
    {
        srt[counter]->ra  = (int)(360.0*(Ra()/D2PI));
        srt[counter]->dec = (int)(360.0*(Dec()/D2PI));
        srt[counter]->nr  = counter;

        if (counter%step==0)
            cout << "." << flush;

        counter++;
    }
    cout << "done." << endl << endl;

    /* sort entries */
    cout << "Sorting coordinates..." << flush;
    rekMergesort(srt, entries, 0, entries-1);
    cout << "done." << endl << endl;

    cout << "Writing sorted catalogue..." << flush;
    FILE *f   = fopen("sao-sort.cmp", "w");
    FILE *idx = fopen("sao-sort.idx", "w");

    int ra=0, ral=0;
    int dec=0, decl=0;
    for (int i=0; i<entries; i++)
    {
        GetEntry(srt[i]->nr);

        ra  = (int)(360.0*Ra()/D2PI);
        dec = (int)(360.0*Dec()/D2PI);

        if (ra!=ral || dec!=decl)
        {
            if (ra!=ral)
                cout << "." << flush;
            fprintf(idx, "%3d %3d %10d\n", ra, dec, i);
        }

        ral = ra;
        decl = dec;

        fprintf(f, String());
        if (i%5000==0)
            cout << "." << flush;
    }
    fclose(idx);
    fclose(f);
    cout << "done." << endl;
}

