//
// This File contains the definition of the MGCoordinates-class
//
//   Author: Thomas Bretz
//   Version: V1.0 (1-8-2000)

#include "MGAccuracy.h"

#include <iostream.h>  // cout

#include <TArc.h>
#include <TLine.h>
#include <TText.h>
#include <TWbox.h>
#include <TList.h>
#include <TGaxis.h>
#include <TCanvas.h>

#include "coord.h"

ClassImp(MGAccuracy);

void MGAccuracy::DrawCoordinateSystem()
{
    TWbox box;
    box.DrawWbox(-145*2, 145*2, -15*2, 120*2,  18,  2, 1);

    TText text;
    text.SetTextAlign(22);  // centered, centered (s.TAttText)
    text.DrawText(-80*2, 132.5*2, "Tracking Error [']");


    TArc arc;
    arc.SetFillStyle(4000);  // transparent
    arc.SetFillColor(39);
    arc.SetLineColor(3);     // green
    arc.SetLineStyle(2);     // dashed  (s. TAttLine)
    arc.DrawArc(0, 0, 79.1/2.);        // 0.5se

    arc.SetLineColor(5);     // yellow
    arc.DrawArc(0, 0, 79.1);            // 1.0se

    arc.SetLineColor(2);     // red
    arc.DrawArc(0, 0, 79.1*2.);         // 2.0se


    text.SetTextAlign(11);  // left, bottom (s.TAttText)
    text.SetTextColor(3);
    text.DrawText(220, -220, "0.5se");

    text.SetTextColor(5);
    text.DrawText(220, -250, "1.0se");

    text.SetTextColor(2);
    text.DrawText(220, -280, "2.0se");


    TLine line;
    line.DrawLine(-65*4,     0, 65*4,    0);
    line.DrawLine(    0, -65*4,    0, 65*4);

    //
    // Can be replaced by TGaxis axe; in a later root version
    // than 3.01/06. I talked to Rene
    //
    TGaxis *axe;
    axe = new TGaxis(-60*4,   0, 60*4,  0,  -4, 4, 30204, "+-N");
    axe->SetTitle("Az"); // \xb0
    axe->SetBit(kCanDelete);
    axe->Draw();

    axe = new TGaxis(  0, -60*4,  0, 60*4,  -4, 4,   304, "+-N");
    axe->SetTitle("Zd"); // \xb0
    axe->SetLabelOffset(-0.02);
    axe->SetBit(kCanDelete);
    axe->Draw();

    //
    // FIXME? Use TAxis?
    //
/*
    TLine line;
    line.SetLineColor(13);
    line.SetLineStyle(3);  // dotted  (s. TAttLine)
    line.DrawLine(-30, -65, -30,  65);
    line.DrawLine(-65, -30,  65, -30);
    line.DrawLine( 30, -65,  30,  65);
    line.DrawLine(-65,  30,  65,  30);

    line.DrawLine(-15, -65, -15,  65);
    line.DrawLine(-65, -15,  65, -15);
    line.DrawLine( 15, -65,  15,  65);
    line.DrawLine(-65,  15,  65,  15);

    line.DrawLine(-45, -65, -45,  65);
    line.DrawLine(-65, -45,  65, -45);
    line.DrawLine( 45, -65,  45,  65);
    line.DrawLine(-65,  45,  65,  45);

    line.SetLineColor(12);
    line.SetLineStyle(2);  // dashed  (s. TAttLine)
    line.DrawLine(-60, -65, -60,  65);
    line.DrawLine(-65, -60,  65, -60);
    line.DrawLine( 60, -65,  60,  65);
    line.DrawLine(-65,  60,  65,  60);

    line.SetLineColor(1);  // black
    line.SetLineStyle(1);  // solid  (s. TAttLine)
    line.DrawLine(-65,   0, 65,  0);
    line.DrawLine(  0, -65,  0, 65);

    line.DrawLine(-1,  60, 1,  60);
    line.DrawLine(-1, -60, 1, -60);
    line.DrawLine(-1,  30, 1,  30);
    line.DrawLine(-1, -30, 1, -30);

    line.DrawLine( 60, -1,  60, 1);
    line.DrawLine(-60, -1, -60, 1);
    line.DrawLine( 30, -1,  30, 1);
    line.DrawLine(-30, -1, -30, 1);

    TText text;
    text.SetTextAlign(22);  // centered, centered (s.TAttText)
    text.DrawText(60, 5, "dAz[\xb0]");
    text.DrawText(0, 70, "dZd[\xb0]");

    text.SetTextAlign(23);  // centered, centered (s.TAttText)
    text.DrawText(-60, -2, "-1'");
    text.DrawText( 60, -2, "1'");
    text.DrawText(-30, -2, "-30\"");
    text.DrawText( 30, -2, "30\"");

    text.SetTextAlign(32);  // centered, centered (s.TAttText)
    text.DrawText(-2, -60, "-1'");
    text.DrawText(-2,  60, "1'");
    text.DrawText(-2, -30, "-30\"");
    text.DrawText(-2,  30, "30\"");
    */
}

void MGAccuracy::InitText()
{
    fTxt = new TText(280, 280, "0' / 0'");
    fTxt->SetTextAlign(33); // right, top
    fTxt->SetTextColor(10);
    fTxt->Draw();

    fList->Add(fTxt);
}

void MGAccuracy::InitCross()
{
    fLin1 = new TLine(0, 0, 0, 0);
    fLin2 = new TLine(0, 0, 0, 0);

    fLin1->SetLineColor(10); // white (s. TAttFill)
    fLin2->SetLineColor(10); // white
    fLin1->SetLineStyle(1);  // solid (s. TAttLine)
    fLin2->SetLineStyle(1); 

    fLin1->SetLineWidth(2);
    fLin2->SetLineWidth(2);

    fLin1->Draw();
    fLin2->Draw();

    fList->Add(fLin1);
    fList->Add(fLin2);
}

MGAccuracy::MGAccuracy(const TGWindow* p, const UInt_t w)
: MGEmbeddedCanvas("Accuracy", p, w, 75*4)
{
    DrawCoordinateSystem();

    InitText();
    InitCross();

    InitCanvas();

    SetNoContextMenu();
}

MGAccuracy::~MGAccuracy()
{
    //    cout << "MGAccuracy destroyed." << endl;
}

void MGAccuracy::UpdateText(Float_t pzd, Float_t azd, Float_t aaz)
{
    const Float_t d2r = TMath::Pi()/180.;

    pzd *= d2r;
    azd *= d2r;
    aaz *= d2r;

    const double el = TMath::Pi()/2-pzd;

    const double dphi2 = aaz/2.;
    const double cos2  = cos(dphi2)*cos(dphi2);
    const double sin2  = sin(dphi2)*sin(dphi2);
    const double d     = cos(azd)*cos2 - cos(2*el)*sin2;

    //
    // Original:
    //   cos(Zd1)*cos(Zd2)+sin(Zd1)*sin(Zd2)*cos(dAz)
    //
    // Correct:
    //   const double d = cos(azd)*cos2 - cos(el1+el2)*sin2;
    //
    // Estimated:
    //   const double d = cos(azd)*cos2 - cos(2*el)*sin2;
    //

    double dist = acos(d);

    dist *= 3600./d2r;

    int rs = (int)floor(fmod(dist, 60.));
    dist /= 60.;
    int rm = (int)dist;//floor(fmod(dist, 60.));

    char txt[100];
    rm ? sprintf(txt, "%d'%02d\"", rm, rs) : sprintf(txt, "%d\"", rs);

    fTxt->SetText(fTxt->GetX(), fTxt->GetY(), txt);
}

void MGAccuracy::UpdateCross(Float_t x, Float_t y)
{
    fLin1->SetX1(x-5.);
    fLin1->SetX2(x+5.);

    fLin2->SetX1(x-5.);
    fLin2->SetX2(x+5.);

    fLin1->SetY1(y-5.);
    fLin1->SetY2(y+5.);

    fLin2->SetY1(y+5.);
    fLin2->SetY2(y-5.);
}

void MGAccuracy::Update(ZdAz &pos, ZdAz &acc)
{
    //
    // calculate actual time for planet positions
    // acc [deg]
    //
    static int X = ~0;
    static int Y = ~0;

    float x = acc.Az()*3600.; // ["]
    float y = acc.Zd()*3600.; // ["]

    int pixx = (int)(x/fPix);  // [pix]
    int pixy = (int)(y/fPix);  // [pix]

    if (X==pixx && Y==pixy)
        return;

    X = pixx;
    Y = pixy;

    UpdateCross(x, y);
    UpdateText(pos.Zd(), acc.Zd(), acc.Az());

    SetModified();
    UpdateCanvas();
}
