#include "MGCosy.h"

#include "msgqueue.h"

#include <TROOT.h>

#include <TGMenu.h>        // TGPopupMenu
#include <TGButton.h>      // TGButton
#include <TSystem.h>       // gSystem
#include <TGLabel.h>       // TGLabel
#include <TGSplitter.h>    // TGHorizontal3DLine

#include "timer.h"         // Timer

#include "MCosy.h"
#include "MGList.h"
#include "MGCoordinates.h"

#include "Slalib.h"

#define IDM_EXIT 1
#define IDM_TEXT 2

#define kPB_POSITION  0x1001
#define kPB_TRACK     0x1002
#define kPB_STOP      0x1003
#define kPB_CALCALTAZ 0x1004
#define kPB_POLARIS   0x1005

#define kEF_A         0x1010
#define kEF_B         0x1011

void MGCosy::CreateMenu()
{
    fLayMenuBar  = new TGLayoutHints (kLHintsNormal | kLHintsExpandX);
    fLayMenuItem = new TGLayoutHints (kLHintsNormal, 0, 4, 0, 0);

    //
    //  crate the menu bar
    //
    TGPopupMenu *fFileMenu = new TGPopupMenu(fClient->GetRoot());
    fFileMenu->AddEntry ("Exit", IDM_EXIT) ;
    fFileMenu->Associate(this);
    fList->Add(fFileMenu);

    //
    //  the button messages are handled by main frame (this)
    //
    TGMenuBar *fMenuBar = new TGMenuBar(this, 1, 1, kHorizontalFrame);
    fMenuBar->AddPopup("File", fFileMenu, fLayMenuItem);
    AddFrame(fMenuBar);
    fList->Add(fMenuBar);

    //
    //  Seperator beyonf menubar
    //
    TGHorizontal3DLine *fLineSep = new TGHorizontal3DLine(this);
    AddFrame(fLineSep, fLayMenuBar);
    fList->Add(fLineSep);

}

void MGCosy::CreateLabel()
{
    fLabel1 = new TGLabel*[3];
    fLabel1[0] = new TGLabel(this, "00000"); // Max: 16384
    fLabel1[0]->SetTextJustify(kTextRight);
    fLabel1[0]->Move(5, 40);
    fList->Add(fLabel1[0]);
    //    AddFrame(fLabel1[0], new TGLayoutHints(kLHintsNormal, 0, 0, 0, 0));
    fLabel1[1] = new TGLabel(this, "000");   // Max: 256
    fLabel1[1]->SetTextJustify(kTextRight);
    fLabel1[1]->Move(48, 40);
    fList->Add(fLabel1[1]);
    //    AddFrame(fLabel1[1], new TGLayoutHints(kLHintsNormal, 0, 0, 0, 0));
    fLabel1[2] = new TGLabel(this, "000");   // Max: 256
    fLabel1[2]->SetTextJustify(kTextRight);
    fLabel1[2]->Move(75, 40);
    fList->Add(fLabel1[2]);
    //    AddFrame(fLabel1[2], new TGLayoutHints(kLHintsNormal, 9, 9, 9, 9));

    fLabel2 = new TGLabel*[3];
    fLabel2[0] = new TGLabel(this, "00000");
    fLabel2[0]->SetTextJustify(kTextRight);
    fLabel2[0]->Move(5, 60);
    fList->Add(fLabel2[0]);
    //    AddFrame(fLabel2[0], new TGLayoutHints); //(kLHintsNormal, 0, 0, 0, 0));
    fLabel2[1] = new TGLabel(this, "000");
    fLabel2[1]->SetTextJustify(kTextRight);
    fLabel2[1]->Move(48, 60);
    fList->Add(fLabel2[1]);
    //    AddFrame(fLabel2[1], new TGLayoutHints); //(kLHintsNormal, 1, 0, 0, 0));
    fLabel2[2] = new TGLabel(this, "000");
    fLabel2[2]->SetTextJustify(kTextRight);
    fLabel2[2]->Move(75, 60);
    fList->Add(fLabel2[2]);
    //    AddFrame(fLabel2[2], new TGLayoutHints); //(kLHintsNormal, 2, 0, 0, 0));

    fLabel3 = new TGLabel*[3];
    fLabel3[0] = new TGLabel(this, "00000");
    fLabel3[0]->SetTextJustify(kTextRight);
    fLabel3[0]->Move(5, 80);
    fList->Add(fLabel3[0]);
    //    AddFrame(fLabel3[0]); //, new TGLayoutHints(kLHintsNormal, 0, 0, 0, 0));
    fLabel3[1] = new TGLabel(this, "000");
    fLabel3[1]->SetTextJustify(kTextRight);
    fLabel3[1]->Move(48, 80);
    fList->Add(fLabel3[1]);
    //    AddFrame(fLabel3[1]); //, new TGLayoutHints(kLHintsNormal, 1, 0, 0, 0));
    fLabel3[2] = new TGLabel(this, "000");
    fLabel3[2]->SetTextJustify(kTextRight);
    fLabel3[2]->Move(75, 80);
    fList->Add(fLabel3[2]);
    //    AddFrame(fLabel3[2]); //, new TGLayoutHints(kLHintsNormal, 2, 0, 0, 0));
}

void MGCosy::CreateButton()
{
    TGTextButton *fButton1 = new TGTextButton(this, "Position Zd/Az", kPB_POSITION);
    TGTextButton *fButton2 = new TGTextButton(this, "Track   Ra/Dec", kPB_TRACK);
    TGTextButton *fButton3 = new TGTextButton(this, "Stop",           kPB_STOP);
    TGTextButton *fButton4 = new TGTextButton(this, "Calc     Zd/Az", kPB_CALCALTAZ);
    TGTextButton *fButton5 = new TGTextButton(this, "Set Polaris",    kPB_POLARIS);
    fButton1->Move(110,  40);
    fButton2->Move(110,  65);
    fButton3->Move(260,  90);
    fButton4->Move(110,  90);
    fButton5->Move(110, 115);
    fButton1->SetToolTipText("Move Telescope to Zd/Az position.");
    fButton2->SetToolTipText("Track the coordinates given in Ra/Dec.");
    fButton3->SetToolTipText("Stop movement of telescope.");
    fButton4->SetToolTipText("Calculate Zd/Az corresponding to Ra/Dec.");
    fButton5->SetToolTipText("Set the actual position as the position of Polaris.");
    fList->Add(fButton1);
    fList->Add(fButton2);
    fList->Add(fButton3);
    fList->Add(fButton4);
    fList->Add(fButton5);
}

MGCosy::MGCosy(MsgQueue *q, const TGWindow *p, UInt_t w, UInt_t h)
    : TGMainFrame(p, w, h), fQueue(q)
{
    fList = new MGList;

    CreateMenu();
    CreateLabel();
    CreateButton();

    fCoord = new MGCoordinates(this, kTRUE,
                                "Coordinate 1 [\xb0]:", "Coordinate 2 [\xb0]:");
    fCoord->Move(10, 160);
    fList->Add(fCoord);

    //
    //   Map the window, set up the layout, etc.
    //
    SetWMSizeHints(350, 250, 350, 250, 10, 10 ) ;  // set the smallest and biggest size of the Main frame

    MapSubwindows();
    Layout();

    SetWindowName("Cosy Main Window");
    SetIconName("Cosy");

    MapWindow();
}



// ======================================================================

MGCosy::~MGCosy()
{
    delete fLayMenuBar;
    delete fLayMenuItem;

    fList->Delete();
    delete fList;
}
// ======================================================================

void MGCosy::CloseWindow()
{
    // Got close message for this MainFrame. Calls parent CloseWindow()
    // (which destroys the window) and terminate the application.
    // The close message is generated by the window manager when its close
    // window menu item is selected.

    gSystem->ExitLoop();
    //  gSystem->DispatchOneEvent(kTRUE);

    //    TGMainFrame::CloseWindow();
    //  gROOT->GetApplication()->Terminate(0);
}

#include <iostream.h>

Bool_t MGCosy::ProcessMessage(Long_t msg, Long_t mp1, Long_t mp2)
{
    //
    // This processing is serialized!
    //
    switch (GET_MSG(msg))
    {
    case kC_COMMAND:
        switch (GET_SUBMSG(msg))
        {
        case kCM_BUTTON:

            switch (mp1)
            {
            case kPB_POSITION:
                cout << "Start positioning." << endl;
                {
                    XY xy = fCoord->GetCoordinates();
                    ZdAz dest(xy.X(), xy.Y());
                    cout << dest.Zd() << kDEG << " " << dest.Az() << kDEG << endl;
                    fQueue->PostMsg(WM_POSITION, &dest, sizeof(dest));
                }
                cout << "PostMsg(WM_POSITION) returned." << endl;
                return kTRUE;

            case kPB_TRACK:
                cout << "Start tracking." << endl;
                {
                    XY xy = fCoord->GetCoordinates();
                    RaDec dest(xy.X(), xy.Y());
                    cout << dest.Ra() << kDEG << " " << dest.Dec() << kDEG << endl;
                    fQueue->PostMsg(WM_TRACK, &dest, sizeof(dest));
                }
                cout << "PostMsg(WM_TRACK) returned." << endl;
                return kTRUE;

            case kPB_STOP:
                cout << "Sending stop movement msg." << endl;
                fQueue->PostMsg(WM_STOP, 0, 0);
                cout << "PostMsg(WM_STOP) returned." << endl;
                return kTRUE;

            case kPB_CALCALTAZ:
                {
                    Timer t;
                    t.GetTime();

                    Slalib sla;
                    sla.Set(t.GetMjd());

                    XY xy = fCoord->GetCoordinates();
                    RaDec rd(xy.X(), xy.Y());

                    cout << "Ra/Dec: " << rd.Ra() << kDEG << " " << rd.Dec() << kDEG << endl;
                    ZdAz aa=sla.CalcZdAz(rd*D2PI/360.0)*360.0/D2PI;
                    cout << "Zd/Az: " << aa.Zd() << kDEG << " " << aa.Az() << kDEG << endl;
                }
                return kTRUE;

            case kPB_POLARIS:
                fQueue->PostMsg(WM_POLARIS, 0, 0);
                return kTRUE;

            default:
                return kTRUE;
            }
            break;

        case kCM_MENU:

            switch (mp1)
            {
            case IDM_EXIT:
                CloseWindow();
                return kTRUE;

            default:
                return kTRUE;
            }
            return kTRUE;

        default:
            return kTRUE;
        }

    default:
        return kTRUE;
    }

    //
    // Start a thread to process the message.
    //
    // fQueue->PostMsg(msg, mp1, mp2);
    return kTRUE;

}
