#ifndef MCOSY_H
#define MCOSY_H

#include "coord.h"
#include "msgqueue.h"
#include "network.h"
#include "MThread.h"

#define kDEG ((char)0x9c)  // Linux 'ø'

#define WM_WAIT      WM_NULL
#define WM_PRESET    0x1000
#define WM_POSITION  0x1001
#define WM_TRACK     0x1002
#define WM_STOP      0x1003
#define WM_POLARIS   0x1004

class ShaftEncoder;
class Macs;
class MGCosy;
class MCosy;

class MTTalk : public MThread
{
private:
    MCosy *fCosy;

    void *Thread();

public:
    MTTalk(MCosy *cosy) : MThread(false), fCosy(cosy)
    {
        SetPriority(10);
        Detach();
        Start();
    }
    ~MTTalk() { cout << "~MTTalk::MTTalk" << endl; }
};


class TTimer;
class MCosy : public Network, public MsgQueue, public TObject
{
    friend class MTTalk;

private:
    enum
    {
        kError    = 0x01,
        kMoving   = 0x02,
        kTracking = 0x04,
        kStopping = 0x08,
        kStopped  = 0x10
    };

    ShaftEncoder *fZd1;
    ShaftEncoder *fZd2;
    ShaftEncoder *fAz;

    Macs *fMac1;
    Macs *fMac2;
    Macs *fMac3;

    MGCosy *fWin;

    TTimer *fUpdateGui;
    MTTalk *fTTalk;       // should be outsourced, like the starguider.
                          // with a generic interface to both...

    ZdAz  fTrackingError; // Tracking Offset between SE and calc-pos [re]
    ZdAz  fOffset;        // Offset between se and re coordinate system [re]
    RaDec fRaDec;         // Position to track
    int   fTracking;      // Flag for present tracking action
    ZdAz  fAccuracy;      // Actual accuracy of Tracking
    ZdAz  fVelocity;      // Actual velocity of Tracking

    UInt_t fStatus;

    void SetStatus(UInt_t stat) { fStatus = stat; }
    UInt_t GetStatus() const { return fStatus; }

    ZdAz GetRePos();
    ZdAz GetRePosPdo();
    ZdAz GetSePos();     // [se]

    Bool_t RequestRePos();
    Bool_t SetVelocity(ZdAz v);
    void SetPosVelocity(const Float_t ratio, Float_t vel, Float_t acc);

    void DoRelPos(const ZdAz &rd, const Bool_t axe1, const Bool_t axe2);

    void InitTracking();
    void LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const;

    void TalkThread();

    int  SetPosition(const ZdAz &dst);

    void TerminateApp();

    void TrackPosition(const RaDec &dst); // ra, dec [rad]

    int StopWaitingForSDO() const;
    void CheckForError();

    void StopMovement();
    void WaitForEndMovement();

public:
    MCosy(const char *dev, const int baud, MLog &out=gLog);
    ~MCosy();

    void Start();
    void Stop();

    void *Proc(int msg, void *mp);

    Bool_t HandleTimer(TTimer *t);

    static ZdAz CorrectTarget(const ZdAz &src, const ZdAz &dst);
    //    static ZdAz RaDec2ZdAz(const double mjd, const RaDec &pos, const RaDec &pm=RaDec(0,0));

    ClassDef(MCosy, 0)
};

#endif
