#ifndef COSY_MCosy
#define COSY_MCosy

//#include "coord.h"
#include "msgqueue.h"
#include "MPointing.h"

#ifndef MARS_MThread
#define COSY_MThread
#include "MThread.h"
#endif

#ifndef COSY_Network
#include "network.h"
#endif
#ifndef MARS_MObservatory
#include "MObservatory.h"
#endif
#ifndef ROOT_TMutex
#include <TMutex.h>
#endif

#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_CALIB        0x1004
#define WM_TPOINT       0x1005
//#define WM_NEWTRACK     0x1006
#define WM_LOADBENDING  0x1007
#define WM_RESETBENDING 0x1008
#define WM_CALCALTAZ    0x1009
#define WM_HOME         0x100a
#define WM_TESTSE       0x100b
#define WM_GEAR         0x100c
#define WM_DISPLAY      0x100d
#define WM_TRACKPOS     0x100e
#define WM_POSITION1    0x100f
#define WM_ENDSWITCH    0x1010
#define WM_GRB          0x1011
#define WM_PREPS        0x1012
#define WM_ARM          0x1013
#define WM_STARGTPOINT  0x1014
#define WM_STARGMODE    0x1015
#define WM_CELEST       0x1016
#define WM_MOON         0x1017
#define WM_LEDS         0x2D37

class Dkc;

class MGCosy;
class MCosy;
class MStarguider;
class MDriveCom;
class MEnv;

class TTimer;

class MCosy : public Network, public MsgQueue, public TObject
{
    friend class MSlewing;
    friend class MTracking;

private:
    const MObservatory::LocationName_t fObservatory;

    MStarguider *fStarguider;

    Dkc *fMac1;
    Dkc *fMac2;

    MGCosy    *fWin;
    MDriveCom *fCom;

    TTimer    *fUpdateGui;

    TMutex fMutexGui;

    ZdAz     fTrackingError; // [rad] Tracking Offset between SE and calc-pos
    ZdAz     fZdAzSoll;      // [rad] Soll position when moving
    RaDec    fRaDec;         // Position to track
    Double_t fMJD;           // MJD corresponding to fZdAzSoll
    Double_t fHourAngle;     // Hour Angle of Position to track
    ZdAz     fAccuracy;      // Actual accuracy of Tracking
    ZdAz     fMin;
    ZdAz     fMax;

    MPointing fBending;

    UInt_t fStatus;

    std::ofstream *fOutTp;
    MLog     *fOutRep;

    TString fFilePrepos;

    ZdAz AlignTrackingPos(ZdAz pointing) const;
    Bool_t CheckRange(const ZdAz &d) const;
    Double_t Starguider(Double_t mjd, ZdAz &dest) const;

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

    int  SetPosition(const ZdAz &dst, Bool_t track=kFALSE);
    void TrackPlanet(Int_t id, Double_t offset, Double_t angle);
    void TrackMoon(Double_t wobble, Double_t offset);
    void TrackPosition(const RaDec &dst);    // ra, dec [rad]
    void TrackPositionGRB(const RaDec &dst); // ra, dec [rad]

    void TerminateApp();

    int StopWaitingForSDO() const;
    void CheckForError();

    void StopMovement();

    void WaitForEndMovement();

    void Constructor(Int_t id1, Int_t id2);
    //void ConstructorSE(Int_t id1, Int_t id2, Int_t id3);
    //void ConstructorDemo();

    void ReadConfig(MEnv &env);

    bool CheckNetwork();

    void Start() { }

public:
    MCosy(MEnv &env, MDriveCom *com);
    ~MCosy();

    void Start(MEnv &env);
    void Stop();

    Int_t Proc(int msg, void *mp);

    Bool_t HandleTimer(TTimer *t);

    ZdAz GetPointingPos(void) const;
    void SetStarguider(MStarguider *s) { fStarguider = s; }

    static TString GetFileName(const char *path, const char *name, const char *ext);

    MGCosy *GetWin() { return fWin; }

    ZdAz GetSePos() const; // [revolutions]

    MLog *GetOutRep() { return fOutRep; }

    MDriveCom *GetDriveCom() { return fCom; }

    ClassDef(MCosy, 0)
};

#endif
