#include <iostream>
#include <iomanip>
#include <fstream>

#include <TSystem.h>
#include <TApplication.h>

#include "MCosy.h"
#include "MTime.h"
#include "MLogManip.h"

#include "MStarguider.h"

#define EXPERT

#define clog(txt) \
    { \
    const Bool_t is = lout.IsOutputDeviceEnabled(MLog::eStdout); \
    lout << edev(MLog::eStdout) << txt << endl; \
    if (is) \
    lout.EnableOutputDevice(MLog::eStdout); \
    }

/* ---------------------------------------------------------------------- */
int main(int argc, char **argv)
{
    gLog << "==================================================" << endl;
    gLog << "                    Cosy V0.1                     " << endl;
    gLog << "       Magic Drive Control System Software        " << endl;
    gLog << "            Compiled on <" << __DATE__ << ">"       << endl;
    gLog << "               Using ROOT v" << ROOTVER             << endl;
    gLog << "==================================================" << endl;
    gLog << endl;

    Int_t channel = 0;
    for (int i=0; i<argc; i++)
    {
        TString arg(argv[i]);
        if (arg=="-1")
            channel = 1;
        if (arg=="-0")
            channel = 0;
        if (arg=="-c")
            channel = -1;
    }

    //
    // this must move to MGCosy !!!!
    //
    const TString name = MCosy::GetFileName("log", "cosy", "log");
    cout << "Open Logfile: " << name << endl;

    MLog *l = new MLog(name, kTRUE);
    MLog &lout = *l;
    lout.SetNoColors();

    MTime now(-1);
    clog("Starting Cosy at " << now << " ...");

    //
    // start the main window
    //
    clog("- Initialising Root environment.");

    // FIXME: Fails deleteing something in TGClient::fWlist
    TApplication *app=new TApplication("App", &argc, argv);

    if (gROOT->IsBatch())
    {
        cout << "ERROR - Cannot run in Batch mode!" << endl;
        return 0;
    }

    //
    // Create the Network. Device: /dev/dpm_00, Rate: 500kbps
    //
    clog("- Constructing MCosy.");
/*
    //
    // check for the right usage of the program
    //
    int mode = 0;
    if (argc==2 && (argv[1][0]=='-' || argv[1][1]=='m'))
        switch (argv[1][2])
        {
        case '0':      // standard
            mode = 0;
            break;
        case '1':      // SE mode
            mode = 1;
            break;
        case '2':      // GUI demo mode
            mode = 2;
            break;
        }
*/
    MCosy *cosy = new MCosy("/dev/dpm_00", 125, lout);

    clog("- Starting MCosy.");
#ifndef EXPERT
    lout.DisableOutputDevice(MLog::eStdout);
#endif
    cosy->Start();

    MStarguider *client=0;
    if (channel>=0)
    {
        clog("- Starting Camera.");
        client=new MStarguider(MObservatory::kMagic1, channel);
        cosy->SetStarguider(client);
        client->SetCosy(cosy);
    }

    clog("- Starting mainloop.");
#ifndef EXPERT
    lout.DisableOutputDevice(MLog::eStdout);
#endif
    app->Run(kTRUE);

    if (channel>=0)
    {
        client->SetCosy(NULL);
        cosy->SetStarguider(NULL);
        clog("- Stopping starg.");
        delete client;
    }

    clog("- Stopping cosy.");
    cosy->Stop();

    now.Now();
    clog(now << ": MCosy stopped.");

    delete cosy;

    now.Now();
    clog("Terminating cosy at " << now);

    delete l;

    cout << "The End." << endl;
}
