#ifndef COSY_MBending
#define COSY_MBending

#include <TROOT.h>

#include <fstream.h>

#include "coord.h"

class TMinuit;

class MBending
{
private:
    Double_t fIe   ; // [rad] Index Error in Elevation
    Double_t fIa   ; // [rad] Index Error in Azimuth
    Double_t fCa   ; // [rad] Left-Right Collimation Error
    Double_t fAn   ; // [rad] Azimuth Axis Misalignment (N-S)
    Double_t fAw   ; // [rad] Azimuth Axis Misalignment (E-W)
    Double_t fNpae ; // [rad] Az-El Nonperpendicularity
    Double_t fNrx  ; // [rad] Nasmyth rotator displacement, horizontan
    Double_t fNry  ; // [rad] Nasmyth rotator displacement, vertical
    Double_t fCrx  ; // [rad] Alt/Az Coude Displacement (N-S)
    Double_t fCry  ; // [rad] Alt/Az Coude Displacement (E-W)
    Double_t fEces ; // [rad] Elevation Centering Error (sin)
    Double_t fAces ; // [rad] Azimuth Centering Error (sin)
    Double_t fEcec ; // [rad] Elevation Centering Error (cos)
    Double_t fAcec ; // [rad] Azimuth Centering Error (cos)
    Double_t fMagic1; // [rad] Magic Term (what is it?)
    Double_t fMagic2; // [rad] Magic Term (what is it?)


    void Clear()
    {
        fIe  =0 ; // Index Error in Elevation
        fIa  =0 ; // Index Error in Azimuth
        fCa  =0 ; // Left-Right Collimation Error
        fAn  =0 ; // Azimuth Axis Misalignment (N-S)
        fAw  =0 ; // Azimuth Axis Misalignment (E-W)
        fNpae=0 ; // Az-El Nonperpendicularity
        fNrx =0 ; // Nasmyth rotator displacement, horizontan
        fNry =0 ; // Nasmyth rotator displacement, vertical
        fCrx =0 ; // Alt/Az Coude Displacement (N-S)
        fCry =0 ; // Alt/Az Coude Displacement (E-W)
        fEces=0 ; // Elevation Centering Error (sin)
        fAces=0 ; // Azimuth Centering Error (sin)
        fEcec=0 ; // Elevation Centering Error (cos)
        fAcec=0 ; // Azimuth Centering Error (cos)
        fMagic1=0; // Azimuth Centering Error (cos)
        fMagic2=0; // Azimuth Centering Error (cos)
    }

public:
    MBending() { Clear(); }

    void Load(const char *name);
    void Save(const char *name);

    void Reset();

    ZdAz  Correct(const ZdAz &zdaz) const;
    AltAz Correct(const AltAz &aaz) const;

    ZdAz  CorrectBack(const ZdAz &zdaz) const;
    AltAz CorrectBack(const AltAz &aaz) const;

    ZdAz operator()(const ZdAz &zdaz) const { return Correct(zdaz); }
    AltAz operator()(const AltAz &aaz) const { return Correct(aaz); }

    ZdAz operator()(const ZdAz &zdaz, void (*fcn)(ZdAz &zdaz, Double_t *par)) const
    {
        Double_t par[16];
        GetParameters(par);
        ZdAz za = zdaz;
        fcn(za, par);
        return za;
    }

    AltAz operator()(const AltAz &aaz, void (*fcn)(AltAz &aaz, Double_t *par)) const
    {
        Double_t par[16];
        GetParameters(par);
        AltAz aa = aaz;
        fcn(aa, par);
        return aa;
    }

    void SetParameters(const Double_t *par, Int_t n=16);
    void GetParameters(Double_t *par, Int_t n=16) const;

    void SetMinuitParameters(TMinuit &m, Int_t n=-1) const;
    void GetMinuitParameters(TMinuit &m, Int_t n=-1);
    void PrintMinuitParameters(TMinuit &m, Int_t n=-1) const;

    /*
     Double_t GetIe() const { return fIe; }
     Double_t GetIa() const { return fIa; }
     Double_t GetCa() const { return fCa; }
     Double_t GetAn() const { return fAn; }
     Double_t GetAw() const { return fAw; }
     Double_t GetNrx() const { return fNrx; }
     Double_t GetNry() const { return fNry; }
     Double_t GetCrx() const { return fNrx; }
     Double_t GetCry() const { return fNry; }
     Double_t GetEces() const { return fEces; }
     Double_t GetEcec() const { return fEcec; }
     Double_t GetAces() const { return fAces; }
     Double_t GetAcec() const { return fAcec; }
     Double_t GetNpae() const { return fNpae; }
     */

    ClassDef(MBending, 1)
};

#endif
