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

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

#ifndef WINCE
  #define ADD_CHEQUE "_AddMerchantCheque"
  #define CARD_AUTHORIZE "_card_authorize12"
  #define DDL_NAME "pilot_nt.dll"
#else
  #define ADD_CHEQUE L"AddMerchantCheque"
  #define CARD_AUTHORIZE L"card_authorize12"
  #define DDL_NAME L"pilot_nt.dll"
#endif

typedef int (*dynamic_add_cheque)(DWORD requestID, const char* pCheque);
typedef int (*dynamic_card_authorize)(char *track2, struct auth_answer12 *auth_answer);

DWORD preauth(dynamic_card_authorize function, DWORD amount, DWORD& requestId)
{
  auth_answer12 argument;

  memset(&argument,0,sizeof(argument));
  argument.ans.TType = OP_PURCHASE;
  argument.ans.Amount = amount;
  std::cout << "Payment authorization. Amount = " << amount << std::endl;
  DWORD result = function(NULL,&argument);
  if (!result)
    requestId = argument.RequestID;

  std::cout << "Operation completed with code '" << result << "'. RequestID:" << argument.RequestID << std::endl;
  return result;
}


DWORD complete_with_cheque(dynamic_add_cheque function, DWORD requestId)
{
  DWORD result = function(requestId, "09876543210987654321poiuytrewq");

  std::cout << "Operation completed with code '" << result << "'." << std::endl;
  return result;
}

DWORD complete_without_cheque(dynamic_add_cheque function, DWORD requestId)
{
  DWORD result = function(requestId, NULL);

  std::cout << "Operation completed with code '" << result << "'." << std::endl;
  return result;
}

DWORD upload_cheques_to_host(dynamic_add_cheque function)
{
  DWORD result = function(0, NULL);

  std::cout << "Operation completed with code '" << result << "'." << std::endl;
  return result;
}

#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 {
    dynamic_add_cheque external_add_cheque = (dynamic_add_cheque)GetProcAddress(dll, ADD_CHEQUE);
    dynamic_card_authorize external_card_authorize = (dynamic_card_authorize)GetProcAddress(dll, CARD_AUTHORIZE);
    if (!external_add_cheque || !external_card_authorize)
    {
      std::cerr << "Required function in " << DDL_NAME << " not found";
      return -2;
    }

    DWORD requestId = 0;
    if(!preauth(external_card_authorize, 10000, requestId))
      complete_with_cheque(external_add_cheque, requestId);

    requestId = 0;
    if(!preauth(external_card_authorize, 10000, requestId))
      complete_without_cheque(external_add_cheque, requestId);

    upload_cheques_to_host(external_add_cheque);
  }
  catch(...)
  {
     std::cerr << "Unhandled exception" << std::endl;
  }
  FreeLibrary(dll);
  return 0;
}