// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "ThriftTest.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>

using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;

using namespace  ::thrift::test;

class ThriftTestHandler : virtual public ThriftTestIf {
 public:
  ThriftTestHandler() {
    // Your initialization goes here
  }

  /**
   * Prints "testVoid()" and returns nothing.
   */
  void testVoid() {
    // Your implementation goes here
    printf("testVoid\n");
  }

  /**
   * Prints 'testString("%s")' with thing as '%s'
   * @param string thing - the string to print
   * @return string - returns the string 'thing'
   * 
   * @param thing
   */
  void testString(std::string& _return, const std::string& thing) {
    // Your implementation goes here
    printf("testString\n");
  }

  /**
   * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false'
   * @param bool  thing - the bool data to print
   * @return bool  - returns the bool 'thing'
   * 
   * @param thing
   */
  bool testBool(const bool thing) {
    // Your implementation goes here
    printf("testBool\n");
  }

  /**
   * Prints 'testByte("%d")' with thing as '%d'
   * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility.
   * @param byte thing - the i8/byte to print
   * @return i8 - returns the i8/byte 'thing'
   * 
   * @param thing
   */
  int8_t testByte(const int8_t thing) {
    // Your implementation goes here
    printf("testByte\n");
  }

  /**
   * Prints 'testI32("%d")' with thing as '%d'
   * @param i32 thing - the i32 to print
   * @return i32 - returns the i32 'thing'
   * 
   * @param thing
   */
  int32_t testI32(const int32_t thing) {
    // Your implementation goes here
    printf("testI32\n");
  }

  /**
   * Prints 'testI64("%d")' with thing as '%d'
   * @param i64 thing - the i64 to print
   * @return i64 - returns the i64 'thing'
   * 
   * @param thing
   */
  int64_t testI64(const int64_t thing) {
    // Your implementation goes here
    printf("testI64\n");
  }

  /**
   * Prints 'testDouble("%f")' with thing as '%f'
   * @param double thing - the double to print
   * @return double - returns the double 'thing'
   * 
   * @param thing
   */
  double testDouble(const double thing) {
    // Your implementation goes here
    printf("testDouble\n");
  }

  /**
   * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data
   * @param binary  thing - the binary data to print
   * @return binary  - returns the binary 'thing'
   * 
   * @param thing
   */
  void testBinary(std::string& _return, const std::string& thing) {
    // Your implementation goes here
    printf("testBinary\n");
  }

  /**
   * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values
   * @param Xtruct thing - the Xtruct to print
   * @return Xtruct - returns the Xtruct 'thing'
   * 
   * @param thing
   */
  void testStruct(Xtruct& _return, const Xtruct& thing) {
    // Your implementation goes here
    printf("testStruct\n");
  }

  /**
   * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct
   * @param Xtruct2 thing - the Xtruct2 to print
   * @return Xtruct2 - returns the Xtruct2 'thing'
   * 
   * @param thing
   */
  void testNest(Xtruct2& _return, const Xtruct2& thing) {
    // Your implementation goes here
    printf("testNest\n");
  }

  /**
   * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs
   *  separated by commas and new lines
   * @param map<i32,i32> thing - the map<i32,i32> to print
   * @return map<i32,i32> - returns the map<i32,i32> 'thing'
   * 
   * @param thing
   */
  void testMap(std::map<int32_t, int32_t> & _return, const std::map<int32_t, int32_t> & thing) {
    // Your implementation goes here
    printf("testMap\n");
  }

  /**
   * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs
   *  separated by commas and new lines
   * @param map<string,string> thing - the map<string,string> to print
   * @return map<string,string> - returns the map<string,string> 'thing'
   * 
   * @param thing
   */
  void testStringMap(std::map<std::string, std::string> & _return, const std::map<std::string, std::string> & thing) {
    // Your implementation goes here
    printf("testStringMap\n");
  }

  /**
   * Prints 'testSet("{%s}")' where thing has been formatted into a string of values
   *  separated by commas and new lines
   * @param set<i32> thing - the set<i32> to print
   * @return set<i32> - returns the set<i32> 'thing'
   * 
   * @param thing
   */
  void testSet(std::set<int32_t> & _return, const std::set<int32_t> & thing) {
    // Your implementation goes here
    printf("testSet\n");
  }

  /**
   * Prints 'testList("{%s}")' where thing has been formatted into a string of values
   *  separated by commas and new lines
   * @param list<i32> thing - the list<i32> to print
   * @return list<i32> - returns the list<i32> 'thing'
   * 
   * @param thing
   */
  void testList(std::vector<int32_t> & _return, const std::vector<int32_t> & thing) {
    // Your implementation goes here
    printf("testList\n");
  }

  /**
   * Prints 'testEnum("%d")' where thing has been formatted into its numeric value
   * @param Numberz thing - the Numberz to print
   * @return Numberz - returns the Numberz 'thing'
   * 
   * @param thing
   */
  Numberz::type testEnum(const Numberz::type thing) {
    // Your implementation goes here
    printf("testEnum\n");
  }

  /**
   * Prints 'testTypedef("%d")' with thing as '%d'
   * @param UserId thing - the UserId to print
   * @return UserId - returns the UserId 'thing'
   * 
   * @param thing
   */
  UserId testTypedef(const UserId thing) {
    // Your implementation goes here
    printf("testTypedef\n");
  }

  /**
   * Prints 'testMapMap("%d")' with hello as '%d'
   * @param i32 hello - the i32 to print
   * @return map<i32,map<i32,i32>> - returns a dictionary with these values:
   *   {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, }
   * 
   * @param hello
   */
  void testMapMap(std::map<int32_t, std::map<int32_t, int32_t> > & _return, const int32_t hello) {
    // Your implementation goes here
    printf("testMapMap\n");
  }

  /**
   * So you think you've got this all worked out, eh?
   * 
   * Creates a map with these values and prints it out:
   *   { 1 => { 2 => argument,
   *            3 => argument,
   *          },
   *     2 => { 6 => <empty Insanity struct>, },
   *   }
   * @return map<UserId, map<Numberz,Insanity>> - a map with the above values
   * 
   * @param argument
   */
  void testInsanity(std::map<UserId, std::map<Numberz::type, Insanity> > & _return, const Insanity& argument) {
    // Your implementation goes here
    printf("testInsanity\n");
  }

  /**
   * Prints 'testMulti()'
   * @param i8 arg0 -
   * @param i32 arg1 -
   * @param i64 arg2 -
   * @param map<i16, string> arg3 -
   * @param Numberz arg4 -
   * @param UserId arg5 -
   * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1
   *    and i64_thing = arg2
   * 
   * @param arg0
   * @param arg1
   * @param arg2
   * @param arg3
   * @param arg4
   * @param arg5
   */
  void testMulti(Xtruct& _return, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> & arg3, const Numberz::type arg4, const UserId arg5) {
    // Your implementation goes here
    printf("testMulti\n");
  }

  /**
   * Print 'testException(%s)' with arg as '%s'
   * @param string arg - a string indication what type of exception to throw
   * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg
   * else if arg == "TException" throw TException
   * else do not throw anything
   * 
   * @param arg
   */
  void testException(const std::string& arg) {
    // Your implementation goes here
    printf("testException\n");
  }

  /**
   * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s'
   * @param string arg - a string indicating what type of exception to throw
   * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception"
   * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2"
   * else do not throw anything
   * @return Xtruct - an Xtruct with string_thing = arg1
   * 
   * @param arg0
   * @param arg1
   */
  void testMultiException(Xtruct& _return, const std::string& arg0, const std::string& arg1) {
    // Your implementation goes here
    printf("testMultiException\n");
  }

  /**
   * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d'
   * sleep 'secondsToSleep'
   * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d'
   * @param i32 secondsToSleep - the number of seconds to sleep
   * 
   * @param secondsToSleep
   */
  void testOneway(const int32_t secondsToSleep) {
    // Your implementation goes here
    printf("testOneway\n");
  }

};

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

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

