//-----------------------------------------------------------------------------
// File          : ControlServerApp.cpp
// Author        : Larry Ruckman  <ruckman@slac.stanford.edu>
// Created       : 10/05/2015
//-----------------------------------------------------------------------------
// Description :
// DebugGui Top Device
//-----------------------------------------------------------------------------
// This file is part of 'Amc Carrier Test Software'.
// It is subject to the license terms in the LICENSE.txt file found in the 
// top-level directory of this distribution and at: 
//    https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 
// No part of 'Amc Carrier Test Software', including this file, 
// may be copied, modified, propagated, or distributed except according to 
// the terms contained in the LICENSE.txt file.
// Proprietary and confidential to SLAC.
//-----------------------------------------------------------------------------
// Modification history :
// 10/05/2015: created
//-----------------------------------------------------------------------------

#include <iomanip>
#include <fstream>
#include <iostream>
#include <signal.h>

#include <execinfo.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

#include <getopt.h>

#include "ControlServer.h"
#include "System.h"
//#include "LegacyControl.h"

#include <cpsw_api_builder.h>
#include <cpsw_api_user.h>
#include <cpsw_yaml.h>
#include <cpsw_preproc.h>

#include <yaml-cpp/yaml.h>

using namespace std;

class TestFailed {};

static void usage(const char *nm)
{
        fprintf(stderr,"Usage: %s [-a <ip_addr>[:<port>[:<stream_port>]]] [-hR] [-V <version>] [-D tdest] [-T timeout]\n", nm);
        fprintf(stderr,"       -a <ip_addr>:  destination IP\n");
        fprintf(stderr,"       -V <version>:  SRP version (1..3)\n");
        fprintf(stderr,"       -D <tdest>  :  use tdest demuxer (SRP)\n");
        fprintf(stderr,"       -T <us>     :  set SRP timeout\n");
        fprintf(stderr,"       -f          :  yaml file to load configuration\n");
        fprintf(stderr,"       -d          :  defaults XML file path\n");
        fprintf(stderr,"       -h          :  print this message\n\n\n");
};


class IYamlSetIP : public IHub::IYamlFixup {
public:
	IYamlSetIP( const char* ip_addr ) : ip_addr_(ip_addr) {}
	virtual void operator()(YAML::Node &node) 
	{
          node["NetIODev"]["ipAddr"] = ip_addr_;
	}

	virtual ~IYamlSetIP() {}
private:
	std::string ip_addr_;
};

int main (int argc, char **argv) 
{  
ControlServer cntrlServer;
string        defFile = "";
bool          stop;
bool          passAddr = false;
YAML::Node doc;
const char *ip_addr = "10.0.2.102";
const char *yaml_doc = "system.yaml";
int        *i_p;
int         vers    = 2;
int         srpTo   = 0;
int         length  = 0;
unsigned    port    = 8192;
int         tDestSRP  = -1;
const char *defaultsPath = "config/defaults.xml";

           for ( int opt; (opt = getopt(argc, argv, "a:V:hD:T:f:d:")) > 0; ) {
                i_p = 0;
                switch ( opt ) {
                        case 'a': ip_addr = optarg; passAddr=true; break;
                        case 'V': i_p     = &vers;      break;
                        case 'S': i_p     = &length;    break;
                        case 'h': usage(argv[0]);
                                return 0;
                        case 'D': i_p     = &tDestSRP;  break;
                        case 'T': i_p     = &srpTo;     break;
                        case 'f': yaml_doc = optarg;    break;
                        case 'd': defaultsPath = optarg; break;
                        default:
                                fprintf(stderr,"Unknown option '%c'\n", opt);
                                usage(argv[0]);
                                throw TestFailed();
                }
                if ( i_p && 1 != sscanf(optarg, "%i", i_p) ) {
                        fprintf(stderr,"Unable to scan argument to option '-%c'\n", opt);
                        throw TestFailed();
                }
        } 

   Hub h;
   try {

//      StreamMuxBuf         muxer;
//      std::string path( yaml_doc );
//      path = path.substr(0, path.find_last_of("\\/"));
//
//      YamlPreprocessor     preprocessor( yaml_doc, &muxer, path.c_str() );
//
//      preprocessor.process();
//
//      std::istream top_preprocessed_stream( &muxer );
//
//      YAML::Node node = YAML::Load( top_preprocessed_stream );
//
      if( passAddr ) {
        IYamlSetIP setIP(ip_addr);
        h = IHub::loadYamlFile( yaml_doc, "NetIODev", NULL, &setIP );
      } else {
        h = IHub::loadYamlFile( yaml_doc, "NetIODev" );
      }

      Path p = IPath::create( h );

      System tester( "ROOT", p->findByName("mmio") , defaultsPath);
   
      cntrlServer.enableSharedMemory("Tester",1);
      port = cntrlServer.startListen(0);
      cntrlServer.setSystem(&tester);
      cout << "Control id = 1" << endl;   

      //Start control server
      stop = false;
      cout << "Starting server at port " << dec << port << endl;
      while ( ! stop ) cntrlServer.receive(100);
      cntrlServer.stopListen();
      cout << "Stopped server" << endl;

   } catch ( string error ) {
      cout << "Caught Error: " << endl;
      cout << error << endl;
      cntrlServer.stopListen();
   } 
   catch (CPSWError &e){
      printf("CPSWError: %s\n", e.getInfo().c_str());
   }
}
