#include <windows.h>
#include <iostream>

#include "..\..\..\..\pilot_nt.h"

#ifndef WINCE
  #define FUNC_NAME "_card_authorize12"
  #define DDL_NAME "pilot_nt.dll"
  #define FINISH_NAME "_PilotCloseReader"
  #define FUNC_ROLLBACK_NAME "_RollbackTrx"
#else
  #define FUNC_NAME L"card_authorize12"
  #define DDL_NAME L"pilot_nt.dll"
#define FINISH_NAME "PilotCloseReader"
#endif

typedef int (*dynamic_function)(char *track2, struct auth_answer12 *auth_answer);
typedef int (*rollback_function)(DWORD dwAmount, char* pAuthCode);

#ifndef WINCE
int main (int argc, char** argv)
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
#endif
{
  HMODULE dll = LoadLibrary(DDL_NAME);
  if (!dll) 
  {
    std::cerr << "pilot_nt.dll not found";
    return -1;
  }

  try
  {
    auth_answer12 argument;
    DWORD amountPurchase = 100000;
    DWORD amountRefund =   1000;
    DWORD result;
    dynamic_function payment = (dynamic_function)GetProcAddress(dll, FUNC_NAME);
    rollback_function rollback = (rollback_function)GetProcAddress(dll, FUNC_ROLLBACK_NAME);

    if (!payment)
    {
      std::cerr << "function " << FUNC_NAME << " in " << DDL_NAME << " not found";
      return -2;
    }
    if (!rollback)
    {
      std::cerr << "function " << FUNC_ROLLBACK_NAME << " in " << DDL_NAME << " not found";
      return -2;
    }
    // purchase
    memset(&argument, 0, sizeof(argument));
    argument.ans.TType = OP_PURCHASE;
    argument.ans.Amount = amountPurchase;
    std::cout << "Operation '" << argument.ans.TType << "'" << std::endl;
    std::cout << "Before start: (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    result = payment(NULL, &argument);
    std::cout << "Operation completed with code '" << result << "'. (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    if (result == 4353)
    {
      result = payment(NULL, &argument);
    }
    // refund
    std::string rrn(argument.RRN);
    memset(&argument, 0, sizeof(argument));
    argument.ans.TType = OP_RETURN;
    argument.ans.Amount = amountRefund;
    memcpy(argument.RRN, rrn.c_str(), rrn.size());
    std::cout << "Operation '" << argument.ans.TType << "'" << std::endl;
    std::cout << "Before start: (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    result = payment(NULL, &argument);
    std::cout << "Operation completed with code '" << result << "'. (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    // cancel for refund
    //memset(&argument, 0, sizeof(argument));
    //argument.ans.TType = OP_RETURN;
    //argument.ans.Amount = amountRefund;
    //memcpy(argument.RRN, rrn.c_str(), rrn.size());
    //std::cout << "Operation '" << argument.ans.TType << "'" << std::endl;
    //std::cout << "Before start: (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    //result = payment(NULL, &argument);
    //std::cout << "Operation completed with code '" << result << "'. (RRN: " << argument.RRN << ", auth code: " << argument.AuthCode << ")" << std::endl;
    result = (DWORD)rollback(argument.ans.Amount, argument.AuthCode);
    std::cout << "Operation 'rollback' completed with code '" << result << "'. (auth code: " << argument.AuthCode << ")" << std::endl;
  }
  catch(...)
  {
    FreeLibrary(dll);
  }
  return 0;
}
