//HelloSvc.h was generated by the thrift compiler 
//so you just need to include it into your code
#include "gen-cpp/HelloSvc.h"
#include "gen-cpp/hello_types.h"

//Hey look, I am including c/c++ stuff
#include <iostream>
#include <unistd.h>

//These are header files for the boiler plate code for 
//estabilishing the connection via internet
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>

//Typical namepaces in c++
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
/* 
 * NOTE be causious about "using namespace std;"
 * it doesn't play well with boost sometimes
 */


//Thrift like to use boost libraries
using std::shared_ptr;

//HelloSvcIf is a virtual class generated by the 
//thrift compilier. You must create a subclass 
//which in this case is called HelloSvcHandler
//and implmemnt the functions you declared in the 
//hello.thrift file
class HelloSvcHandler : virtual public HelloSvcIf {
 public:
  //Just a typical class constructor
  //do whatever you like here
  HelloSvcHandler() {
    // Your initialization goes here
    std::cout<<"Hey look the constructor was called"<<std::endl;
    std::cout<<std::endl;
  }

  void hello_func(std::string& _return) {
    // Your implementation goes here
    std::cout<<std::endl;
    printf("hello_func was called.Client is gonna wait \n"); 
    printf("for an 5 seconds to show that the Client has to wait for the string return \n");
    usleep(5000000);
    printf("Now resuming execution\n");
    _return = "Hey look, I am a string that is from hello_func, my value (which is this sentence) was set in hello_func\n";
    std::cout<<std::endl;
  }

  void hello_func2(const std::string& var1, const int64_t var2) {
    // Your implementation goes here 
    std::cout<<std::endl;
    printf("hello_func2 was called. Now printing the values of var1 and var2\n");
    printf("that you sent over from the client\n");
    printf("Var1:  %s\n",var1.c_str());
    printf("Var2:  %lld\n",var2);
    std::cout<<std::endl;
  }

  void hello_func3(const std::string& var1, const Hello_struct& struct1, const MyInteger var3) {
    // Your implementation goes here
    std::cout<<std::endl;
    printf("hello_func3 was called. Now printing var1, struct1, and var3");
    printf("Var1: %s\n", var1.c_str());
    std::cout<<"Now printing the values of the struct"<<std::endl;
    std::cout<<"Struct num1: "<<struct1.num1<<std::endl;
    std::cout<<"Struct num2: "<<struct1.num2<<std::endl;
    std::cout<<"Struct string1: "<<struct1.string1<<std::endl;

    std::cout<<"Now printing MyInteger typedef:  "<<var3<<std::endl;

  }

};

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<HelloSvcHandler> handler(new HelloSvcHandler());
  shared_ptr<TProcessor> processor(new HelloSvcProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

