#include "StateMachineDimControl.h"
#include "RemoteControl.h"

using namespace std;

// ------------------------------------------------------------------------

#include "Main.h"

template<class T>
int RunShell(Configuration &conf)
{
    StateMachineDimControl::fIsServer = conf.Get<bool>("server");
    return Main::execute<T, StateMachineDimControl>(conf);
}

void SetupConfiguration(Configuration &conf)
{
    po::options_description control("Dim control options");
    control.add_options()
        ("server",       po_bool(false),  "Start dimctrl as a dim server")
        // ("verbosity,v",  var<uint32_t>()->implicit_value(0), "Set a new verbosity level (see MessageImp)")
        // ("quiet,q",      po_bool(false),  "Suppress all output except comments (log-level>=90)")
        ("debug",        po_bool(false),  "Print the labels for debugging purpose")
        ("start",        var<string>(),   "Start a java script with the given name")
        ("batch",        var<string>(),   "Start a batch script with the given name at the given label (script.dim[:N])")
        ("stop",         po_switch(),     "Stop a currently running script")
        ("msg",          var<string>(),   "Send a messageto the chat server.")
        ("user,u",       var<string>(""), "A user name - just for logging purposes (default is ${USER})")
        ;

    conf.AddEnv("user", "USER");

    conf.AddOptions(control);
}

/*
 Extract usage clause(s) [if any] for SYNOPSIS.
 Translators: "Usage" and "or" here are patterns (regular expressions) which
 are used to match the usage synopsis in program output.  An example from cp
 (GNU coreutils) which contains both strings:
  Usage: cp [OPTION]... [-T] SOURCE DEST
    or:  cp [OPTION]... SOURCE... DIRECTORY
    or:  cp [OPTION]... -t DIRECTORY SOURCE...
 */
void PrintUsage()
{
    cout <<
        "The feedback control the BIAS voltages based on the calibration signal.\n"
        "\n"
        "The default is that the program is started without user intercation. "
        "All actions are supposed to arrive as DimCommands. Using the -c "
        "option, a local shell can be initialized. With h or help a short "
        "help message about the usuage can be brought to the screen.\n"
        "\n"
        "Usage: feedback [-c type] [OPTIONS]\n"
        "  or:  feedback [OPTIONS]\n";
    cout << endl;
}

void PrintHelp()
{
    Main::PrintHelp<StateMachineDimControl>();

    /* Additional help text which is printed after the configuration
     options goes here */

    /*
     cout << "bla bla bla" << endl << endl;
     cout << endl;
     cout << "Environment:" << endl;
     cout << "environment" << endl;
     cout << endl;
     cout << "Examples:" << endl;
     cout << "test exam" << endl;
     cout << endl;
     cout << "Files:" << endl;
     cout << "files" << endl;
     cout << endl;
     */
}

int main(int argc, const char* argv[])
{
    Configuration conf(argv[0]);
    conf.SetPrintUsage(PrintUsage);
    Main::SetupConfiguration(conf);
    SetupConfiguration(conf);

    if (!conf.DoParse(argc, argv, PrintHelp))
        return 127;

    //return RunShell<LocalStream>(conf);

    if (!conf.Has("console"))
        return RunShell<RemoteStream>(conf);

    if (conf.Get<int>("console")==0)
        return RunShell<RemoteShell>(conf);
    else
        return RunShell<RemoteConsole>(conf);
}
