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

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

#ifndef WINCE
  #define FUNC_AUTH "_card_authorize8"
  #define FUNC_MULTI_AUTH_COMPLETE "_card_complete_multi_auth8"
  #define DDL_NAME "pilot_nt.dll"
#else
  #define FUNC_AUTH L"card_authorize8"
  #define FUNC_MULTI_AUTH_COMPLETE "card_complete_multi_auth8"
  #define DDL_NAME L"pilot_nt.dll"
#endif

#define CHEQUE_FILENAME "cheque.txt"

typedef int (*dynamic_card_auth)(char *track2, struct auth_answer8 *auth_answer);
typedef int (*dynamic_card_complete_multi_auth8)(char* track2, struct auth_answer8* auth_ans, struct preauth_rec*  pPreAuthList, int NumAuths);

DWORD preauth(dynamic_card_auth card_auth, DWORD amount, char* rrn, char* encryptedData)
{
  auth_answer8 argument;

  memset(&argument,0,sizeof(argument));
  argument.auth_answ.TType = OP_PREAUTH;
  argument.auth_answ.Amount = amount;
  std::cout << "PreAuthorization. Amount = " << amount << std::endl;
  DWORD result = card_auth(NULL, &argument);
  if (!result) {
    strcpy(rrn, argument.RRN);
    strcpy(encryptedData, argument.EncryptedData);
  }

  std::cout << "PreAuthorization finished with code '" << result << "'. RRN:" << argument.RRN << std::endl;
  return result;
}

DWORD few_complete_auth(dynamic_card_complete_multi_auth8 card_complete_multi_auth, DWORD summaryAmount, char* encryptedData, preauth_rec* completions, int count)
{
  auth_answer8 argument;
  
  memset(&argument,0,sizeof(argument));
  argument.auth_answ.TType = OP_COMPLETION;
  argument.auth_answ.Amount = summaryAmount;
  strcpy(argument.EncryptedData, encryptedData);

  DWORD result = card_complete_multi_auth(NULL,&argument, completions, count);

  std::cout << "Authorization completion finished with code '" << result << "'" << std::endl;

  std::ofstream file(CHEQUE_FILENAME);
  file << argument.auth_answ.Check;
  file.close();

  if (argument.auth_answ.Check) {
    std::cout << "Cheque saved to file " << CHEQUE_FILENAME << std::endl;
    //GlobaFree(argument.auth_answ.Check);
  }
  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_card_auth card_auth = (dynamic_card_auth)GetProcAddress(dll, FUNC_AUTH);
    dynamic_card_complete_multi_auth8 card_complete_multi_auth = (dynamic_card_complete_multi_auth8)GetProcAddress(dll, FUNC_MULTI_AUTH_COMPLETE);

    if (!card_auth)
    {
      std::cerr << "card_auth " << FUNC_AUTH << " in " << DDL_NAME << " not found";
      return -2;
    }

    std::vector<preauth_rec> completions;
    DWORD summaryAmount = 0;
    char encryptedData[512];
    std::cout << "Let's perform a few authorizations..." << std::endl;
    for(;;)
    {
      preauth_rec rec;
      memset(&rec, 0 , sizeof(rec));
      int amount = 0;

      std::cout << "Input amount in cents (or 0 to complete): ";

      std::cin >> amount;
      if (amount < 1)
        break;

      rec.Amount = amount;
      summaryAmount += rec.Amount;
      if (preauth(card_auth, (DWORD)amount, rec.RRN, encryptedData))
        break;

      completions.push_back(rec);
    }

    if (completions.size())
      few_complete_auth(card_complete_multi_auth, summaryAmount, encryptedData, &completions[0], completions.size());
    else
    {
       std::cout << "Nothing to complete!\nTools has not succesfully completed operations.";
    }
  }
  catch(...)
  {
    FreeLibrary(dll);
  }
  return 0;
}