#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 (console mode switched off)")
        ("force-console",po_switch(),     "Forces console mode in server-mode.")
        ("debug",        po_bool(false),  "Print the labels for debugging purpose")
        ("start",        var<string>(),   "Start a java script with the given name on the dimctrl-server")
        ("batch",        var<string>(),   "Start a batch script with the given name at the given label (script.dim[:N]) on the dimctrl-server")
        ("stop",         po_switch(),     "Stop a currently running script on the dimctrl-server")
        ("msg",          var<string>(),   "Send a message to the chat server.")
        ("user,u",       var<string>(""), "A user name - just for logging purposes (default is ${USER})")
        ("JavaScript.*", var<string>(""), "Additional arguments which are provided to JavaScripts started in a dimctrl server via the START command")
        ;

    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;

    if (conf.Get<bool>("force-console") && !conf.Has("console"))
        throw runtime_error("--force-console must be used with --console/-c");

    if (conf.Get<bool>("server") && !conf.Get<bool>("force-console"))
        conf.Remove("console");

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

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