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

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

#ifndef WINCE
  #define FUNC_NAME "_card_authorize9"
  #define DDL_NAME "pilot_nt.dll"
  #define FINISH_NAME "_PilotCloseReader"
#else
  #define FUNC_NAME L"card_authorize9"
  #define DDL_NAME L"pilot_nt.dll"
#define FINISH_NAME "PilotCloseReader"
#endif

typedef int (*dynamic_function)(char *track2, struct auth_answer9 *auth_answer);
typedef int (*dynamic_close_reader)();


bool IsCardHolderWantsToPayByCash()
{
  return false; // change it to true is customer wants to pay by cash
}

#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_function payment = (dynamic_function)GetProcAddress(dll, FUNC_NAME);
    if (!payment)
    {
      std::cerr << "function " << FUNC_NAME << " in " << DDL_NAME << " not found";
      return -2;
    }

    dynamic_close_reader close_reader = (dynamic_close_reader)GetProcAddress(dll, FINISH_NAME);
    if (!close_reader)
    {
      std::cerr << "function " << FINISH_NAME << " in " << DDL_NAME << " not found";
      return -2;
    }

    auth_answer9 argument;
    DWORD amountbefore = 100000;
    DWORD amountAfter =   90000;
    std::string hash;

    memset(&argument,0,sizeof(argument));
    argument.ans.TType = OP_PURCHASE;
    argument.ans.Amount = amountbefore;
    std::cout << "Let's try to pay!" << std::endl;
    DWORD result = payment(NULL,&argument);
    // after call 'argument' contains card hash which required for second call
    if (result == 4353)
    {
      std::cout << "Sberbank Spasibo detected!" << std::endl;
      hash = std::string(argument.Hash); // < -- card hash is here now
      if (IsCardHolderWantsToPayByCash())
      {
        // card holder wants to pay by cash
        close_reader();
      }
      else
	  {
        // KKM code can change amount (payment by spasibo)
        argument.ans.Amount = amountAfter;
        result = payment(NULL, &argument);
      }
    }
  
    std::cout << "Operation completed with code '" << result << "'!" << std::endl;
  }
  catch(...)
  {
    FreeLibrary(dll);
  }
  return 0;
}