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

#include "Pos.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <iostream>
#include "db_if.h"
#include "db.h"
#include "sha1.h"

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

using boost::shared_ptr;

using namespace pos;

DbIf * d;

class PosHandler : virtual public PosIf {
 public:
  PosHandler() {
	std::cerr << "Pos server starting.\n";
  }

  void ping() { }

  void getSalt(std::string& _return) {
    _return = d->getSalt();
  }

  int32_t getAccountFromHash(const std::string& dataToHash) {
    return d->getDb().getAccountFromHash(SHA1Hash(dataToHash));
  }

  void getHashesFromAccountId(std::vector<std::string> & _return, const int32_t account) {
    std::list<std::string> rv = d->getDb().getHashesFromAccount(account);
    _return.reserve(rv.size());
    for(std::list<std::string>::iterator p = rv.begin(); p != rv.end(); ++p)
      _return.push_back(*p);
  }

  void getHashesFromAccountName(std::vector<std::string> & _return, const std::string& account) {
    std::list<std::string> rv = d->getDb().getHashesFromAccount(account);
    _return.reserve(rv.size());
    for(std::list<std::string>::iterator p = rv.begin(); p != rv.end(); ++p)
      _return.push_back(*p);
  }

  int32_t getHashAccountBalance(const std::string& dataToHash) {
    return d->getDb().getAccountBalance(SHA1Hash(dataToHash));
  }

  int32_t getIdAccountBalance(const int32_t account) {
    return d->getDb().getAccountBalance(account);
  }

  int32_t getNameAccountBalance(const std::string& account) {
    return d->getDb().getAccountBalance(account);
  }

  int64_t associateHashWithId(const std::string& auth, const std::string& dataToHash, const int32_t account) {
    if(d->consumeKey(auth))
      return d->getDb().associateHash(SHA1Hash(dataToHash), account);
    else
      return 0;
  }

  int64_t associateHashWithName(const std::string& auth, const std::string& dataToHash, const std::string& account) {
    if(d->consumeKey(auth))
      return d->getDb().associateHash(SHA1Hash(dataToHash), account);
    else
      return 0;
  }

  int64_t deassociateHash(const std::string& auth, const std::string& dataToHash) {
    if(d->consumeKey(auth))
      return d->getDb().deassociateHash(SHA1Hash(dataToHash));
    else
      return 0;
  }

  int32_t getUPCPrice(const int64_t upc_high, const int64_t upc_low) {
    UPC u;
    u.l = upc_low;
    u.h = upc_high;
    return d->getDb().getUPCPrice(u);
  }

  int64_t setUPCPrice(const std::string& auth, const int64_t upc_high, const int64_t upc_low, const int32_t price) {
    if(d->consumeKey(auth)) {
      UPC u;
      u.l = upc_low;
      u.h = upc_high;
      return d->getDb().setUPCPrice(u, price);
    } else
      return 0;
  }

  int64_t doTransactionOnHash(const std::string& auth, const std::string& dataToHash, const int32_t delta) {
    if(d->consumeKey(auth))
      return d->getDb().doTransaction(SHA1Hash(dataToHash), delta);
    else
      return 0;
  }

  int64_t doTransactionOnId(const std::string& auth, const int32_t account, const int32_t delta) {
    if(d->consumeKey(auth))
      return d->getDb().doTransaction(account, delta);
    else
      return 0;
  }

  int64_t doTransactionOnName(const std::string& auth, const std::string& account, const int32_t delta) {
    if(d->consumeKey(auth))
      return d->getDb().doTransaction(account, delta);
    else
      return 0;
  }

  int64_t revertTransaction(const std::string& auth, const int64_t serial) {
    if(d->consumeKey(auth))
      return d->getDb().revertTransaction(serial);
    else
      return 0;
  }

  int32_t getStock(const int64_t upc_high, const int64_t upc_low) {
    UPC u;
    u.h = upc_high;
    u.l = upc_low;
    return d->getDb().getStock(u);
  }

  int64_t doStockChange(const std::string& auth, const int64_t upc_high, const int64_t upc_low, const int32_t delta) {
    if(d->consumeKey(auth)) {
      UPC u;
      u.h = upc_high;
      u.l = upc_low;
      return d->getDb().doStockChange(u, delta);
    } else
      return 0;
  }

  void toString(std::vector<std::string> & _return) {
    _return = d->getDb().toString();
  }

};

int main(int argc, char **argv) {
  int port = 9090;

  DbIf ds(argc, argv);
  d = & ds;

  shared_ptr<PosHandler> handler(new PosHandler());
  shared_ptr<TProcessor> processor(new PosProcessor(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;
}

