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

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

#include "MCosy.h"
#include "MLogManip.h"
#include "base/timer.h"

#include "Camera.h"
#include "PngReader.h"
#include "MStarguider.h"

//#define EXPERT
//#define HAVE_CAMERA

#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;

    Timer time;
    time.Now();

    //
    // this must move to MGCosy !!!! (or MApplication)
    //
    int i=0;
    char name[100];
    while (1)
    {
        sprintf(name, "log/cosy%03d.log", i++);
        if (gSystem->AccessPathName(name, kFileExists))
            break;
    }

    cout << "Open Logfile: " << name << endl;

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

    clog("Starting Cosy at " << time << " ...");

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

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

    //
    // 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(mode, "/dev/dpm_00", 125, lout);

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

    clog("- Starting Camera.");
#ifdef HAVE_CAMERA
    MStarguider *client=new MStarguider(MObservatory::kMagic1);
    Camera *cam = new Camera(*client);
    cam->Loop(0);

    cosy->SetStarguider(client);
    client->SetCosy(cosy);
#endif
    clog("- Starting mainloop.");
#ifndef EXPERT
    lout.DisableOutputDevice(MLog::eStdout);
#endif
    app->Run(kTRUE);
#ifdef HAVE_CAMERA
    client->SetCosy(NULL);
    cosy->SetStarguider(NULL);

    clog("- Stopping starg.");
    cam->ExitLoop();
    delete cam;
    delete client;
#endif
    clog("- Stopping cosy.");
    cosy->Stop();

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

    delete cosy;

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

    delete l;

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

}
