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

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

#ifndef WINCE  
  #define DDL_NAME "pilot_nt.dll"
#else
  #define DDL_NAME L"pilot_nt.dll"
#endif




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

//read card context
void read_card_context(std::string& theHash)
{   
   std::cout << "Launch ReadCardContext." << std::endl;
   //allocate context
   CONTEXT_PTR ctx=ctxAlloc();

   //set card type 
   ctxSetInt(ctx, PAR_CARD_TYPE, CT_VAS_AND_PAY);

   int error = ReadCardContext(ctx);

   std::cout << "ReadCardContext result=" << error << std::endl;

   if (error==ERR_OK)
   {
     std::cout << "Retrive context vars..." << std::endl;
     int ivalue;
     char buf[128];

     error = ctxGetInt(ctx, PAR_LLT_ID, &ivalue);
     if (error==ERR_OK)
     {
       std::cout << "Loyalty Id = " << ivalue << std::endl;
     }
     else
     {
       std::cout << "Loyalty Id is not found in context" << std::endl;
     }

     error = ctxGetString(ctx, PAR_PAN, buf, sizeof(buf));
     if (error==ERR_OK)
     {
       std::cout << "PAN = " << buf << std::endl;
     }
     else
     {
       std::cout << "PAN is not found in context" << std::endl;
     }

     error = ctxGetString(ctx, PAR_HASH, buf, sizeof(buf));
     if (error==ERR_OK)
     {
       theHash=buf;
       std::cout << "HASH = " << buf << std::endl;
     }
     else
     {
       std::cout << "HASH is not found in context" << std::endl;
     }

     error = ctxGetInt(ctx, PAR_CARD_TYPE, &ivalue);
     if (error==ERR_OK)
     {
       std::cout << "Card type = " << ivalue << std::endl;
     }
     else
     {
       std::cout << "Card type is not found in context" << std::endl;
     }

     error = ctxGetInt(ctx, PAR_OWN_CARD, &ivalue);
     if (error==ERR_OK)
     {
       std::cout << "Own card = " << ivalue << std::endl;
     }
     else
     {
       std::cout << "Own card is not found in context" << std::endl;
     }

     error = ctxGetInt(ctx, PAR_VAS_LENGTH, &ivalue);
     if (error==ERR_OK)
     {
       std::cout << "vas xml length = " << ivalue << std::endl;

       char* vas=new char [ivalue+1];
       error = ctxGetString(ctx, PAR_VAS_STRING, vas, ivalue+1);
       if (error == ERR_OK)
       {
        std::cout << "vas xml string " << std::endl << vas << std::endl;
       }
       else
       {
         std::cout << "vas xml string is not found in context" << std::endl;
       }
     }
     else
     {
       std::cout << "vas length is not found in context" << std::endl;
     }
   }
   ctxFree(ctx);
}

//function read card and return last for digits and firt 24 ascii symbols of the pans hash with 'H' prefix
void read_card()
{
  char last4[32];
  char hash[MAX_ASCII_HASH+1];
  std::cout << "Launch ReadCard. The function return the first 24 ascii characters of the hash from the card number, followed by the 'H'symbol on the left." << std::endl;
  int result=ReadCard(last4, hash);
  std::cout << "ReadCard completed with code " << result << "!" << std::endl;
  std::cout << "HASH = " << hash << std::endl;
  std::cout << "Last for digit = " << last4 << std::endl;
}

void read_card_sb()
{
  char last4[32];
  char hash[MAX_ASCII_HASH+1]; //additional space for 'H' charaster
  std::cout << "Launch ReadCardSB. The function returns the full hash from the card number, followed by the 'H'symbol on the left." << std::endl;
  std::cout << "If the card is not issued by Sberbank, function return error 4180." << std::endl;
  int result=ReadCardSB(last4, hash);
  std::cout << "Last for digit = " << last4 << std::endl;
  std::cout << "ReadCardSB completed with code '" << result << "'!" << std::endl;
  std::cout << "HASH = " << hash << std::endl; 
}



void read_card_track3()
{
  char last4[32];
  char hash[MAX_ASCII_HASH+1]; //additional space for 'H' charaster
  char track3[MAX_TRACK3+1];   //additional space for terminated '\0'
  std::cout << "Launch ReadCardTrack3." << std::endl;
  std::cout << "If the card is not issued by Sberbank, function return error 4180." << std::endl;
  int result=ReadCardTrack3(last4, hash, track3);
  std::cout << "ReadCardSB completed with code '" << result << "'!" << std::endl;
  std::cout << "Last for digit = " << last4 << std::endl;
  std::cout << "HASH = " << hash << std::endl;
  std::cout << "Track3 = " << track3 << std::endl;
}

void read_card_with_type()
{
  char last4[32];
  char hash[MAX_ASCII_HASH+1]; //additional space for 'H' charaster
  int  cardType;
  int  isSberbankCard;
  std::cout << "Launch ReadCardWithType." << std::endl;
  int result=ReadCardWithType(last4, hash, &cardType, &isSberbankCard);
  std::cout << "ReadCardWithType completed with code '" << result << "'!" << std::endl;
  std::cout << "Last for digit = " << last4 << std::endl;
  std::cout << "HASH = " << hash << std::endl;
  std::cout << "Card type = " << cardType << std::endl;
  std::cout << "Is Sberbank card = " << isSberbankCard << std::endl;  
}


void read_masked_card_with_type()
{
  char pan[MAX_PAN];
  char hash[MAX_ASCII_HASH+1]; //additional space for 'H' charaster
  int  cardType;
  int  isSberbankCard;
  std::cout << "Launch ReadMaskedCardWithType." << std::endl;
  int result=ReadMaskedCardWithType(pan, hash, &cardType, &isSberbankCard);
  std::cout << "ReadMaskedCardWithType completed with code '" << result << "'!" << std::endl;
  std::cout << "Masked pan = " << pan << std::endl;
  std::cout << "HASH = " << hash << std::endl;
  std::cout << "Card type = " << cardType << std::endl;
  std::cout << "Is Sberbank card = " << isSberbankCard << std::endl;  
}

void read_track2()
{
  char track2[MAX_TRACK2];
  std::cout << "Launch ReadTrack2." << std::endl;
  int result=ReadTrack2(track2);
  std::cout << "ReadTrack2 completed with code '" << result << "'!" << std::endl;
  std::cout << "track2 = " << track2 << std::endl;
  //ReadTrack2;
}


void read_card_and_name()
{  
  char track2[MAX_TRACK2];
  char valThru[8];
  char name[MAX_CLIENT_NAME];
  std::cout << "Launch ReadCardAndName." << std::endl;
  int result=ReadCardAndName(track2, valThru, name);
  std::cout << "ReadCardAndName completed with code '" << result << "'!" << std::endl;
  std::cout << "track2 = " << track2 << std::endl;
  std::cout << "valThru = " << valThru << std::endl;
  std::cout << "name = " << name << std::endl;
}

void read_card_full()
{
  char pan[MAX_CARD_NUM+1];
  char valThru[8];  
  std::cout << "Launch ReadCardFull." << std::endl;
  int result=ReadCardFull(pan, valThru);
  std::cout << "ReadCardFull completed with code '" << result << "'!" << std::endl;
  std::cout << "pan = " << pan << std::endl;
  std::cout << "valThru = " << valThru << std::endl;
}

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


void WaitAnyKey(void)
{
  std::cout<<"Press any key dor continue,,,"<<std::endl;
  getchar();
  std::cout<<std::endl;
}


#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);
  const char* nameOfTheUncknownFunction=NULL;
  HMODULE dll = LoadPilotNt(DDL_NAME, &nameOfTheUncknownFunction);
  if (!dll) 
  {
    if (!nameOfTheUncknownFunction)
    {
      std::cerr << "pilot_nt.dll not found";
      return -1;
    }
    else
    {
      std::cerr << "function " << nameOfTheUncknownFunction << " in " << DDL_NAME << " not found";
      return -2;
    }    
  }

  CONTEXT_PTR ctx=NULL;

  try {

    read_card();

    WaitAnyKey();

    read_card_sb();

    WaitAnyKey();

    read_card_track3();

    WaitAnyKey();

    read_card_with_type();

    WaitAnyKey();

    read_masked_card_with_type();

    WaitAnyKey();

    read_track2();

    WaitAnyKey();

    read_card_and_name();
    
    WaitAnyKey();

    read_card_full();

    WaitAnyKey();

    std::string theHash;
    //read card context
    std::cout << std::endl << "Lets try payment with hash.\nFirst step - call ReadCardContext for read card.\nSecond step - call card_authorize15 with returned from read card hash" << std::endl;
    read_card_context(theHash);

    //read card and pay
    auth_answer14 argument;
    DWORD amount = 90000;
    std::string hash;

    //allocate context
    CONTEXT_PTR ctx=ctxAlloc();

    
    memset(&argument,0,sizeof(argument));
    argument.ans.TType = OP_PURCHASE;
    argument.ans.Amount = amount;
    argument.ans.CType=0;
    std::cout << "Let's try to pay!" << std::endl;


    DWORD result = card_authorize15(&theHash[0], &argument, NULL, 0, ctx);
      
    std::cout << "Operation completed with code '" << result << "'!" << std::endl;

    WaitAnyKey();

    if (argument.ans.Check)
      ::GlobalFree(argument.ans.Check);

  }
  catch(...)
  {

  }

  ctxFree(ctx);

  FreePilotNt(dll);
  return 0;
}

