#ifndef IMAGEINFODATA_H
#define IMAGEINFODATA_H

#include <QString>
#include <QPointF>
#include <QVector>
#include <QVariant>
#include <QPainterPath>
#include <wcslib/wcs.h>
#include <cmath>
#include <memory>

namespace LibXISF { struct FITSKeyword; struct Property; }

class Database;

struct FITSRecord
{
    QByteArray key;
    QVariant value;
    QByteArray comment;
    bool xisf = false;
    bool editable() const;
    FITSRecord(){}
    FITSRecord(const QByteArray &key, const QVariant &value, const QByteArray &comment);
    FITSRecord(const LibXISF::FITSKeyword &record);
    FITSRecord(const LibXISF::Property &property);
};

class SkyPoint
{
    double ra = NAN;
    double dec = NAN;
public:
    SkyPoint();
    SkyPoint(double ra, double dec);
    void set(double ra, double dec);
    double RA() const { return ra; }
    double RAHour() const { return ra / 15.0; }
    double DEC() const { return dec; }
    QString toString() const;
    QString RAString() const;
    QString DECString() const;
    static double fromHMS(const QString &hms);
    static double fromDMS(const QString &dms);
    static QString toHMS(double decHour);
    static QString toDMS(double deg);
    SkyPoint operator+(const SkyPoint &p);
};

struct SkyPointScale
{
    SkyPoint point;
    //arcsec per pixel
    bool scaleValid = false;
    double scaleLow = 0.0;
    double scaleHigh = 10000.0;
};

struct SkyObject
{
    QString name;
    QString name2;
    SkyPoint skyPoint;
    double maj_ax;
    double min_ax;
    double pos_ang;
    double mag;
    QPointF pixel;
};

struct SkyGrid
{
    bool empty = true;
    QPainterPath grid;
    QVector<QPair<QPointF, QString>> text;
    QVector<SkyObject> objects;
    double rot_ang = 0;
    void clear();
};

class WCSDataT
{
    int nwcs = 0;
    struct wcsprm *wcs = nullptr;
    int width;
    int height;
    void freeWCS();
public:
    WCSDataT(int width, int height, char *header, int nrec);
    WCSDataT(int width, int height, const QVector<FITSRecord> &header);
    WCSDataT(const WCSDataT &) = delete;
    ~WCSDataT();
    bool pixelToWorld(const QPointF &pixel, SkyPoint &point) const;
    bool worldToPixel(const SkyPoint &point, QPointF &pixel) const;
    bool calculateBounds(double &minRa, double &maxRa, double &minDec, double &maxDec, double &crVal1, double &crVal2) const;
    bool valid() const { return wcs; };
    SkyPointScale getRaDecScale() const;
    SkyGrid prepareGrid(uint32_t w, uint32_t h, Database *database);
};

struct ImageInfoData
{
    QVector<FITSRecord> fitsHeader;
    QVector<QPair<QString, QString>> info;
    std::shared_ptr<WCSDataT> wcs;
    SkyPointScale getCenterRaDec() const;
    int index = 0;
    int num = 1;
};

typedef enum
{
    None,
    Statistics,
    Peaks,
    Stars,
}AnalyzeLevel;

Q_DECLARE_METATYPE(ImageInfoData);

#endif // IMAGEINFODATA_H
