// Validator.cpp : XMLRPC server based on the compliancy test at validator.xmlrpc.com.
//
#include "XmlRpc.h"
using namespace XmlRpc;

#include <iostream>


XmlRpcServer s;


// One argument is passed, an array of structs, each with a member named curly with 
// an integer value. Return the sum of those values.

class ArrayOfStructsTest : public XmlRpcServerMethod
{
public:
  ArrayOfStructsTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.arrayOfStructsTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "ArrayOfStructsTest\n";
    XmlRpcValue& arg1 = params[0];
    int n = arg1.size(), sum = 0;
    for (int i=0; i<n; ++i) 
      sum += int(arg1[i]["curly"]);

    result = sum;
  }
} arrayOfStructsTest(&s);


// This handler takes a single parameter, a string, that contains any number of predefined 
// entities, namely <, >, &, ' and ".
// The handler must return a struct that contains five fields, all numbers: ctLeftAngleBrackets, 
// ctRightAngleBrackets, ctAmpersands, ctApostrophes, ctQuotes. 
// To validate, the numbers must be correct.

class CountTheEntities : public XmlRpcServerMethod
{
public:
  CountTheEntities(XmlRpcServer* s) : XmlRpcServerMethod("validator1.countTheEntities", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "CountTheEntities\n";
    std::string& arg = params[0];
    int ctLeftAngleBrackets = 0;
    int ctRightAngleBrackets = 0;
    int ctAmpersands = 0;
    int ctApostrophes = 0;
    int ctQuotes = 0;

    int n = int(arg.length());
    for (int i=0; i<n; ++i)
      switch (arg[i])
      {
        case '<': ++ctLeftAngleBrackets; break;
        case '>': ++ctRightAngleBrackets; break;
        case '&': ++ctAmpersands; break;
        case '\'': ++ctApostrophes; break;
        case '\"': ++ctQuotes; break;
      }

    result["ctLeftAngleBrackets"] = ctLeftAngleBrackets;
    result["ctRightAngleBrackets"] = ctRightAngleBrackets;
    result["ctAmpersands"] = ctAmpersands;
    result["ctApostrophes"] = ctApostrophes;
    result["ctQuotes"] = ctQuotes;
  }
} countTheEntities(&s);



// This handler takes a single parameter, a struct, containing at least three elements 
// named moe, larry and curly, all <i4>s. Your handler must add the three numbers and 
// return the result.

class EasyStructTest : public XmlRpcServerMethod
{
public:
  EasyStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.easyStructTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "EasyStructTest\n";
    XmlRpcValue& arg1 = params[0];
    int sum = int(arg1["moe"]) + int(arg1["larry"]) + int(arg1["curly"]);
    result = sum;
  }
} easyStructTest(&s);


// This handler takes a single parameter, a struct. Your handler must return the struct.

class EchoStructTest : public XmlRpcServerMethod
{
public:
  EchoStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.echoStructTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "EchoStructTest\n";
    result = params[0];
  }
} echoStructTest(&s);



// This handler takes six parameters, and returns an array containing all the parameters.

class ManyTypesTest : public XmlRpcServerMethod
{
public:
  ManyTypesTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.manyTypesTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "ManyTypesTest\n";
    result = params;
  }
} manyTypesTest(&s);



// This handler takes a single parameter, which is an array containing between 100 and 
// 200 elements. Each of the items is a string, your handler must return a string 
// containing the concatenated text of the first and last elements.


class ModerateSizeArrayCheck : public XmlRpcServerMethod
{
public:
  ModerateSizeArrayCheck(XmlRpcServer* s) : XmlRpcServerMethod("validator1.moderateSizeArrayCheck", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "ModerateSizeArrayCheck\n";
    std::string s = params[0][0];
    s += params[0][params[0].size()-1];
    result = s;
  }
} moderateSizeArrayCheck(&s);


// This handler takes a single parameter, a struct, that models a daily calendar.
// At the top level, there is one struct for each year. Each year is broken down
// into months, and months into days. Most of the days are empty in the struct
// you receive, but the entry for April 1, 2000 contains a least three elements
// named moe, larry and curly, all <i4>s. Your handler must add the three numbers
// and return the result.

class NestedStructTest : public XmlRpcServerMethod
{
public:
  NestedStructTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.nestedStructTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "NestedStructTest\n";
    XmlRpcValue& dayStruct = params[0]["2000"]["04"]["01"];
    int sum = int(dayStruct["moe"]) + int(dayStruct["larry"]) + int(dayStruct["curly"]);
    result = sum;
  }
} nestedStructTest(&s);



// This handler takes one parameter, and returns a struct containing three elements, 
// times10, times100 and times1000, the result of multiplying the number by 10, 100 and 1000.

class SimpleStructReturnTest : public XmlRpcServerMethod
{
public:
  SimpleStructReturnTest(XmlRpcServer* s) : XmlRpcServerMethod("validator1.simpleStructReturnTest", s) {}

  void execute(XmlRpcValue& params, XmlRpcValue& result)
  {
    std::cerr << "SimpleStructReturnTest\n";
    int n = params[0];
    result["times10"] = n * 10;
    result["times100"] = n * 100;
    result["times1000"] = n * 1000;
  }
} simpleStructReturnTest(&s);



int main(int argc, char* argv[])
{
  if (argc != 2) {
    std::cerr << "Usage: Validator port\n";
    return -1;
  }
  int port = atoi(argv[1]);

  XmlRpc::setVerbosity(5);

  // Create the server socket on the specified port
  s.bindAndListen(port);

  // Wait for requests indefinitely
  s.work(-1.0);

  return 0;
}

