#include "MGStarg.h"

#include <iostream.h>  // cout

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

#include <MHexagon.h>

#include "coord.h"
#include "MTime.h"

ClassImp(MGStarg);

void MGStarg::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, "Misspointing [min]");

    MHexagon hex;
    hex.SetFillColor(39);
    hex.SetFillStyle(4000);
    hex.SetLineColor(17);
    hex.DrawHexagon(0,0,177.5*2);

    text.SetTextAlign(11);  // left, bottom (s.TAttText)
    text.SetTextColor(3);
    text.DrawText(160, -220, "0.0125 deg");

    text.SetTextColor(5);
    text.DrawText(160, -250, "0.025 deg");

    text.SetTextColor(2);
    text.DrawText(160, -280, "0.05 deg");


    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();
}

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

    fList->Add(fTxt);
}

void MGStarg::InitBar()
{
    fBar = new TLine(0, 0, 0, 0);
    fBar->SetLineColor(kBlack);
    fBar->SetLineStyle(1);
    fBar->SetLineWidth(5);
    fBar->Draw();

    fList->Add(fBar);
}

void MGStarg::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);
}

MGStarg::MGStarg(const TGWindow* p, const UInt_t w)
: MGEmbeddedCanvas("Starg", p, w, 300)
{
    // FIXME: Overload MapWindow in newer Root versions to remove
    //        the contents of the graph!
    fGraph = new TGraph;
    fGraph->SetPoint(0, 0, 0);
    fGraph->SetLineColor(kBlue);
    fGraph->SetMarkerColor(kBlue);
    fGraph->SetMarkerStyle(kFullDotMedium);
    fGraph->Draw("LP");
    fList->Add(fGraph);
    //fGraph->SetNameTitle("AccVsT", "Accuracy vs Min of Time");
    //fGraph->Draw("APL");
    //fGraph->SetMarkerSize(2);

    DrawCoordinateSystem();

    InitText();
    InitCross();
    InitBar();

    InitCanvas();

    SetNoContextMenu();

    MTime t(-1);
    fTime = t.GetAxisTime();
}

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

// dist [deg]
void MGStarg::UpdateText(Float_t dist)
{
    dist *= 3600.; // [sec]

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

    dist /= 60.;   // [min]
    int rm = (int)dist;

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

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

    fBar->SetY2(dist*60); // [sec]
    if (dist<1.5)
        fBar->SetLineColor(kGreen);
    else
        if (dist<3)
            fBar->SetLineColor(kYellow);
        else
            fBar->SetLineColor(kRed);

    SetModified();
}

// dist [deg]
void MGStarg::UpdateGraph(Float_t dist)
{
    MTime t(-1);
    const Double_t dtime = t.GetAxisTime()-fTime; // range [-0.5h, 0h]

    dist *= 60; // min

    static int odist = -1;
    if (odist==(int)(dist*10*60) && dtime<10)
        return;

    odist = (int)(dist*10*60);

    fGraph->SetPoint(fGraph->GetN(), dtime, dist*60);

    const Double_t ntime = dtime;
    for (int i=0; i<fGraph->GetN(); i++)
    {
        Double_t x, y;
        fGraph->GetPoint(i, x,       y);
        fGraph->SetPoint(i, x-ntime, y);
        //cout << i << ":  " << x-ntime << " / " << y << endl;
    }
    while (fGraph->GetN()>0)
    {
        Double_t x, y;
        fGraph->GetPoint(0, x, y);

        if (x==-ntime && y==0)
        {
            fGraph->RemovePoint(0);
            continue;
        }

        if (x>-4.75*60)
            break;

        fGraph->RemovePoint(0);
    }

    fTime = t.GetAxisTime();

    SetModified();

}

void MGStarg::Update(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;

    double dist = acos(d)*TMath::RadToDeg();

    UpdateText(dist);
    UpdateGraph(dist);
}

void MGStarg::UpdateCross(Float_t x, Float_t y)
{
    //
    // x["], y["]
    //
    static int X = ~0;
    static int Y = ~0;

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

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

    X = pixx;
    Y = pixy;

    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.);

    SetModified();
}

void MGStarg::Update(ZdAz &pos, ZdAz &acc)
{

    UpdateCross(acc.Az()*3600., acc.Zd()*3600.);
    Update(pos.Zd(), acc.Zd(), acc.Az());

    UpdateCanvas();
}










