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

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

#ifndef WINCE
  #define FUNC_AUTH "_card_authorize6_ext"  
  #define DLL_NAME "pilot_nt.dll"
#else
  #define FUNC_AUTH L"card_authorize6_ext"
  #define DLL_NAME L"pilot_nt.dll"
#endif

#define CHEQUE_FILENAME "cheque.txt"

extern HMODULE LoadPilotNt(const char* name, const char** nameOfTheUncknownFunction);
extern void    FreePilotNt(HMODULE dll);

DWORD payment_with_requisites(OperationTypes operation, DWORD amount, const char* rrn, const char *tagValue, DWORD paymentTag, std::string& out_rrn)
{
	payment_info_item infoItem, *pItem;
	auth_answer6 argument;

  pItem=NULL;
	memset(&infoItem, 0, sizeof(infoItem));
	memset(&argument, 0, sizeof(argument));
	// fill argument
	argument.auth_answ.TType = operation;
  argument.auth_answ.Amount = amount;
  if (rrn)
	{
    strncpy(argument.RRN, rrn, sizeof(argument.RRN));
    argument.RRN[sizeof(argument.RRN)-1]=0;

	}

	// fill payment info item
  if (tagValue && paymentTag)
  {
	  infoItem.dwTag = paymentTag;
	  if (tagValue)
	  {
		  strncpy(infoItem.Value, tagValue, sizeof(infoItem.Value));
      infoItem.Value[sizeof(infoItem.Value)-1]=0;
	  }
	  infoItem.pNextItem = NULL;
    pItem=&infoItem;
  }

	DWORD result = card_authorize6_ext(NULL, &argument, pItem);
	std::cout << "Operation finished with code '" << result << "'. RRN:" << argument.RRN << std::endl;

  if (result==0 && argument.RRN[0])
  {
    out_rrn.assign(argument.RRN);
  }

  if (argument.auth_answ.Check)
    ::GlobalFree(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
{
  //_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);

	const char *nameOfTheUncknownFunction = NULL;
	HMODULE dll = LoadPilotNt(DLL_NAME, &nameOfTheUncknownFunction);
	if (!dll) 
	{
		std::cerr << DLL_NAME << " not found";
		return -1;
	}
	try 
	{
    std::string rrn, payment_rrn;
		char sampleTicketForPayment[MAX_PAYMENT_ITEM] = "5552450571078";
    char sampleTicketForRefund[MAX_PAYMENT_ITEM] = "5552450570111"; 
    char sampleTicketForRefund2[MAX_PAYMENT_ITEM] = "5552450570112"; 
    DWORD tag = 0xDF0D;

    std::cout << "Start payment for 1100.00" << std::endl;
    DWORD result =  payment_with_requisites(OP_PURCHASE, 110000, NULL, NULL, 0, rrn);
    if (result == 0)
    {
      payment_rrn = rrn;//save for cancel. If you cancel without a RRN and the terminal has several operations for the same amount on the same card, the terminal will display a list of operations to select the operation to cancel.
      std::cout << "Link ticket "<<sampleTicketForPayment<<" to trx with rrn "<<rrn<< std::endl;
      result = payment_with_requisites(OP_SEND_TICKETS, 0, rrn.c_str(), sampleTicketForPayment, tag, rrn);
    }

    std::cout << "Start refund another ticket for 1100.00" << std::endl;
    result =  payment_with_requisites(OP_RETURN, 110000, NULL, NULL, 0, rrn);
    if (result == 0)
    {
      std::cout << "Link ticket "<<sampleTicketForRefund<<" to trx with rrn "<<rrn<< std::endl;
      result = payment_with_requisites(OP_SEND_TICKETS, 0, rrn.c_str(), sampleTicketForRefund, tag, rrn);
    }

    std::cout << "Yet another refund for 1100.00" << std::endl;
    result =  payment_with_requisites(OP_RETURN, 110000, NULL, sampleTicketForRefund, tag, rrn);

    std::cout << "Cancel first payment transaction for 1100.00" << std::endl;
    result =  payment_with_requisites(OP_CANCEL, 110000, payment_rrn.c_str(), NULL, 0, rrn);

     std::cout << "Close day and upload batch" << std::endl;
     auth_answer auth;
     memset(&auth, 0, sizeof(auth));
     result =  close_day(&auth);

     if (auth.Check)
     {
       std::cout << auth.Check << std::endl;
       ::GlobalFree(auth.Check);
     }

    std::cout << "press any key to continue..." << std::endl;
    getchar();
	}
	catch(...)
	{
		
	}
  FreeLibrary(dll);
	return 0;
}
