//---------------------------------------------------------------------------
#include <inifiles.hpp>
#include <vcl\Clipbrd.hpp>

#include <vcl.h>
#pragma hdrstop

#include "tickets.h"
#include "crd_ctrl.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "DigitNum"
#pragma resource "*.dfm"
TfTickets *fTickets;
//---------------------------------------------------------------------------
__fastcall TfTickets::TfTickets(TComponent* Owner)
        : TForm(Owner)
{
  ticketE = new TStringList;
  ticketS = new TStringList;

  Height = 290;
  TbTickets->Active = false;
  TbVentas->Active = true;
  TbPrecios->Active = true;
  // Cargar la configuración de LMs
  AnsiString E, S;
  TIniFile *ini;
  ini = new TIniFile( ExtractFileDir( Application->ExeName ) +  "\\CAP.INI"  );
  // General
  E    = ini->ReadString(  "CAP_c", "IDsLegoE", "1;" );
  S    = ini->ReadString(  "CAP_c", "IDsLegoS", "2;" );


  precioInicial=ini->ReadFloat(  "CAP_g", "precioInicial", 0.0 );
  precioMinuto= ini->ReadFloat(  "CAP_g", "precioMinuto", 0.0 );

  // Ticket de entrada
  int i;
  AnsiString cab,key;
  ticketE->Clear();
  i=1;
  while(1){
        key=AnsiString("cab")+AnsiString(i);
        cab=ini->ReadString("ticketE",key,"<<EOF>>");
        if ( cab!="<<EOF>>" )
                ticketE->Add(cab);
        else
                break;
        i++;
  }
  // Ticket de salida
  ticketS->Clear();
  i=1;
  while(1){
        cab=ini->ReadString("ticketS",AnsiString("cab")+AnsiString(i),"<<EOF>>");
        if ( cab!="<<EOF>>" )
                ticketS->Add(cab);
        else
                break;
        i++;
  }


  delete ini;

  int *ID, nL;
  ObtenDirLEGOS( E, nL, &ID );
  for ( i=0; i<nL; i++ ) ComboBox1->Items->Add( "Entrada ;O"+AnsiString( ID[i] ) );
  ObtenDirLEGOS( S, nL, &ID );
  for ( i=0; i<nL; i++ ) ComboBox1->Items->Add( "Salida  ;O"+AnsiString( ID[i] ) );
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::ObtenDirLEGOS(AnsiString cadena, int &nLEGOS, int **ID)
{
  char *pDir, buff[80], *pbuff;
  nLEGOS = 0; int i = 1, j=0;

          while ( i <= cadena.Length() )
          {
           if ( cadena[i] == ';' ) nLEGOS++;
           i++;
          }

  (*ID) = new int[nLEGOS];
  i = 1; pbuff = buff;
          while ( i <= cadena.Length() )
          {
           if ( cadena[i] == ';' )
           {
            *pbuff = '\0';
            try {
                        (*ID)[j++] = AnsiString( buff ).ToInt();
                } catch(...) {
                        nLEGOS--;
                        ShowMessage( "La configuración de direcciones LEGO'S es incorrecta" );
                }
                pbuff = buff; i++;
            }else{
                *(pbuff++) = cadena[i];
                i++;
            }
           }
}
//---------------------------------------------------------------------------
int __fastcall TfTickets::NDias( TDateTime E, TDateTime S )
{
 int dS, dE;

 dE = E;
 dS = S;

 return ( S-E );
}
//---------------------------------------------------------------------------
int __fastcall TfTickets::NMinutos( TDateTime hE, TDateTime hS )
{
              unsigned short HH, MM, SS, MS;
              int RetroDias = 1, MinutosDentro = 0;
              TDateTime TD;
              if ( hS <  hE )
              {
                TDateTime S(00,00,00,00);
                RetroDias = -1;
                TD = (S - hE) + hS;
              } else {
                TD =(hS - hE);
              }
              TD.DecodeTime( &HH, &MM, &SS, &MS );
              MinutosDentro = HH*60 + MM;
              return (MinutosDentro * RetroDias);
}
//---------------------------------------------------------------------------
int __fastcall TfTickets::obtenerTicket(void)
{
  int pref, upref, cont;

  upref=0;
  sql->SQL->Clear();
  sql->SQL->Add("SELECT Prefijo,Contador FROM 'datos\\contadores' WHERE Id=1");
  sql->Active=true;

  cont = sql->FieldByName("Contador")->AsInteger;
  if ( cont>1000 ) upref=1;
  pref = sql->FieldByName("Prefijo")->AsInteger+upref;

  sql->SQL->Clear();
  sql->SQL->Add("UPDATE 'datos\\contadores' SET Prefijo="+AnsiString(pref)+",Contador="+AnsiString(cont+1)+" WHERE Id=1" );
  sql->ExecSQL();

  return ( pref*1000 + cont );
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::BitBtn1Click(TObject *Sender)
{
 TbTickets->Active = true;

 int NTicket;
  if  ( Edit1->Text.IsEmpty() )
  {
            TDateTime fE = fE.CurrentDate();
            TDateTime hE = hE.CurrentTime();
            TbTickets->Insert();
            TbTickets->FieldByName("fechaE")->AsDateTime = fE;
            TbTickets->FieldByName("horaE")->AsDateTime = hE;
            TbTickets->FieldByName("puedeSalir")->AsBoolean = false;
            TbTickets->Post();


            if ( RadioGroup1->ItemIndex==0 )
            {
                    NTicket = TbTickets->FieldByName("id")->AsInteger;
                    NTicket = (NTicket<<1)+1;
                    TbTickets->Edit();
                    TbTickets->FieldByName("Ticket")->AsInteger = 0;
                    TbTickets->FieldByName("idCard")->AsInteger = NTicket;
                    TbTickets->Post();

                    if ( !GrabaTarjeta(NTicket) )
                       TbTickets->Delete();
                    else
                       ShowMessage( "Nº de Ticket: "+AnsiString( NTicket ) );
            } else {
                    NTicket = obtenerTicket();
                    TbTickets->Edit();
                    TbTickets->FieldByName("Ticket")->AsInteger = NTicket;
                    TbTickets->FieldByName("idCard")->AsInteger = 0;
                    TbTickets->Post();


                    //Currency pvp,int mm,TDateTime fechaE,TDateTime fechaS
                    //

                    ticket_Imprimir(NTicket,'E', 0, 0,
                                    TbTickets->FieldByName("fechaE")->AsDateTime+TbTickets->FieldByName("horaE")->AsDateTime,
                                        0  );

            }
            // #############

    Height = 290;
  } else {
    // Buscar ticket y mostrar sus datos...
    try {

// CAMBIADO 30/ABRL/2002
//     NTicket = ( Edit1->Text.ToInt() ) >> 1;
//     if ( TbTickets->Locate( "id", NTicket, TLocateOptions() << loCaseInsensitive << loPartialKey ) )

       AnsiString fieldKey;
       NTicket = Edit1->Text.ToInt();
       if ( RadioGroup1->ItemIndex==0 ) fieldKey = "idCard"; else fieldKey = "Ticket";


       if ( TbTickets->Locate( fieldKey, NTicket, TLocateOptions() << loCaseInsensitive ) )
       {
              TDateTime TD; Currency Coste;
              int DiasDentro, MinutosDentro;
              DiasDentro = NDias( TbTickets->FieldByName("fechaE")->AsDateTime, TDateTime::CurrentDate() );
              MinutosDentro = NMinutos( TbTickets->FieldByName("horaE")->AsDateTime, TDateTime::CurrentTime() );
              if ( MinutosDentro < 0 )
              {
               MinutosDentro = MinutosDentro*(-1);
               DiasDentro--;
              }
              Coste = CalculaCoste( MinutosDentro, DiasDentro );

              int VDig = Coste*100;
              DigitNum1->Value = VDig / 100;
              DigitNum2->Value = VDig -  ( (VDig / 100)*100 );

              Label4->Caption = TDateTime::CurrentTime();
              Label5->Caption = TDateTime::CurrentDate();
              Label3->Caption = AnsiString( DiasDentro ) + " Dias y " + AnsiString( MinutosDentro ) + " minutos.";
              Label6->Caption = TbTickets->FieldByName("fechaE")->AsDateTime;
              Label7->Caption = TbTickets->FieldByName("horaE")->AsDateTime;


              Height = 370;
        }
    } catch(...) {
     ShowMessage( "El formato del Ticket, es incorrecto" );
    }
  }
 TbTickets->Active = false;
}
//---------------------------------------------------------------------------
Currency __fastcall TfTickets::CalculaCoste( int Minutos, int Dias )
{
  Minutos = Minutos+(24*60*Dias);

  return precioMinuto*Minutos+precioInicial;



 Currency MM = 0, DD = 0;
 TbPrecios->First();
 while ( ! TbPrecios->Eof )
 {
   if ( Minutos <= TbPrecios->FieldByName("Tiempo")->AsInteger )
   {
     MM = TbPrecios->FieldByName("Precio")->AsCurrency;
     break;
   }
   TbPrecios->Next();
 }

 if ( Dias > 0 )
 {
  Dias += 9000;
  TbPrecios->First();
  while ( ! TbPrecios->Eof )
  {
    if ( Dias <= TbPrecios->FieldByName("Tiempo")->AsInteger )
    {
      DD = TbPrecios->FieldByName("Precio")->AsCurrency;
      break;
    }
    TbPrecios->Next();
  }
 }

 return ( DD + MM );
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::BitBtn2Click(TObject *Sender)
{
 bool emitir=true;
 if ( Edit1->Text.IsEmpty() ) return;
 TbTickets->Active = true;

 AnsiString fieldKey;
 if ( RadioGroup1->ItemIndex==0 ) fieldKey = "idCard"; else fieldKey = "Ticket";
 if ( TbTickets->Locate( fieldKey, Edit1->Text, TLocateOptions() << loCaseInsensitive << loPartialKey ) )
 {
   emitir = !TbTickets->FieldByName("PuedeSalir")->AsBoolean;

   if ( !emitir )
   {
//        emitir = ( MessageDlg("El ticket "+Edit1->Text+" ya ha sido cobrado. \n ¿Volver a cobrar ahora?",mtInformation, TMsgDlgButtons() << mbYes << mbNo, 0)==mrYes);
        ShowMessage("Este ticket ya ha sido cobrado!");
   }

   if ( emitir )
   {
              // Imprimimos ¿Ticket PAGADAO?
              //ShowMessage( "Aqui debería imprimirse el comprobante de pago" );

              TbTickets->Edit();
              TbTickets->FieldByName("PuedeSalir")->AsBoolean = true;
              TbTickets->Post();

              // Insertamos la venta...
              Currency Importe;
              Importe = (Currency)(DigitNum1->Value * 100 + DigitNum2->Value ) / 100;
              TbVentas->Insert();
              TbVentas->FieldByName("idc")->AsInteger = -1;              // Cliente ocacional
              TbVentas->FieldByName("fechaE")->AsDateTime = TbTickets->FieldByName("fechaE")->AsDateTime;
              TbVentas->FieldByName("horaE")->AsDateTime = TbTickets->FieldByName("horaE")->AsDateTime;
              TbVentas->FieldByName("fechaS")->AsDateTime = TDateTime::CurrentDate();
              TbVentas->FieldByName("fechaP")->AsDateTime = TDateTime::CurrentDate();
              TbVentas->FieldByName("horaS")->AsDateTime = TDateTime::CurrentTime();
              TbVentas->FieldByName("importe")->AsCurrency = Importe;
              TbVentas->FieldByName("pagado")->AsBoolean = true;
              TbVentas->Post();
              //Currency pvp,int mm,TDateTime fechaE,TDateTime fechaS
              //
              int DiasDentro, MinutosDentro;
              DiasDentro = NDias( TbVentas->FieldByName("fechaE")->AsDateTime, TbVentas->FieldByName("fechaS")->AsDateTime );
              MinutosDentro = NMinutos( TbVentas->FieldByName("horaE")->AsDateTime, TbVentas->FieldByName("horaS")->AsDateTime );
              if ( MinutosDentro < 0 )
              {
               MinutosDentro = MinutosDentro*(-1);
               DiasDentro--;
              }


        if ( MessageDlg("¿Imprimir Ticket?",mtInformation, TMsgDlgButtons() << mbYes << mbNo, 0)==mrYes)
              ticket_Imprimir(TbTickets->FieldByName("idCard")->AsInteger,'S', Importe, DiasDentro*1000+MinutosDentro,
                                TbVentas->FieldByName("fechaE")->AsDateTime+TbVentas->FieldByName("horaE")->AsDateTime,
                                TbVentas->FieldByName("fechaS")->AsDateTime+TbVentas->FieldByName("horaS")->AsDateTime  );
//              TbTickets->Delete();
    }
  } else ShowMessage( "Ticket no encontrado" );
  TbTickets->Active = false;

  // Cobrar
  Edit1->Text = "";
  DigitNum1->Value = 0;
  DigitNum2->Value = 0;
  Height = 290;
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::ComboBox1Change(TObject *Sender)
{
  // Mandamos el mensaje de selección al PortaPapeles...
  AnsiString Bra = ComboBox1->Items->Strings[ComboBox1->ItemIndex];
  Bra = "JDsoft:" + Bra.SubString( Bra.Length()-4, Bra.Length() );
  Clipboard()->SetTextBuf( Bra.c_str() );
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::Edit1KeyPress(TObject *Sender, char &Key)
{
 if ( !Edit1->Text.IsEmpty() && Key == VK_RETURN )
         BitBtn1Click( 0 );
}
//---------------------------------------------------------------------------
bool __fastcall TfTickets::GrabaTarjeta(int ID)
{
   bool dev = false;

   TCardCtrl *CCard;
   CCard = new TCardCtrl(this);

   char buf[80];
   CCard->IDcard = ID;

   CCard->GrabaTarjeraClick(0);
   dev = CCard->statusOK;
   if ( !dev )
   {
           ShowMessage( "ERROR DE GRABACION" );
   }
/*
           CCard->LeeTarjeta(buf);
           ShowMessage( AnsiString(buf) );
*/

   if ( CCard->LM_opened ) CCard->CierraPuerto();
   delete CCard;

   return dev;
}
//---------------------------------------------------------------------------

//###########################################################################
void __fastcall TfTickets::ticket_Imprimir(int idt,char tipo,Currency pvp,int mm,TDateTime fechaE,TDateTime fechaS)
{
//ShowMessage( "Nº de Ticket: "+AnsiString( idt ) );return;//BORRAME CUANDO ESTE LISTO
  Currency Importe;
  Importe = (DigitNum1->Value * 100 + DigitNum2->Value ) / 100;


 TStringList *ticket;
 ticket = (tipo=='E'?ticketE:ticketS);

  hCom =  ticket_AbrirPuerto("LPT1");
  int i;
  double sump=0;
  // Nothing
  // Generamos la cabecera
  ticket_writeCOM( "\n" );
  for ( i=0; i<ticket->Count; i++ )
  {
    ticket_writeCOM( ticket_parsearLinea(ticket->Strings[i],idt,pvp,mm,fechaE,fechaS) );
    ticket_writeCOM( "\n" );
  }

 ticket_CerrarPuerto();
}
//---------------------------------------------------------------------------
AnsiString __fastcall TfTickets::ticket_parsearLinea(AnsiString linea, int idt, Currency pvp,int mm, TDateTime fechaE, TDateTime fechaS)
{
  AnsiString dev;
  // Esto será un "simple", buscar y reemplazar...
//  dev = SearchAndReplace( linea, "[fecha]", DateTimePicker1->Date.DateString() );
  dev = ticket_SearchAndReplace( linea, "{idt}", AnsiString(idt) );
  dev = ticket_SearchAndReplace( dev, "{pvp}", FormatCurr( "##,###,##0.#0",pvp) );
  dev = ticket_SearchAndReplace( dev, "{mm}", mm );
  dev = ticket_SearchAndReplace( dev, "{fechaE}", fechaE.DateTimeString() );
  dev = ticket_SearchAndReplace( dev, "{fechaS}", fechaS.DateTimeString() );

  return dev;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TfTickets::ticket_SearchAndReplace(AnsiString l, AnsiString s, AnsiString r )
{
  AnsiString dev;
  int i;
  // Buscamos s en l
  i = l.Pos(s);
  if ( i>0 )
   dev = l.SubString(1,i-1) + r + l.SubString(i+s.Length(),l.Length());
  else
   dev = l;

  return dev;
}
//---------------------------------------------------------------------------
bool __fastcall TfTickets::ticket_writeCOM(AnsiString output)
{
 char string[255], *p;
 string[0]='\0';
 if ( output.data() != NULL )
 {
  // Esto debería estar en el parser
  strcpy( string, (char *)output.data() );
  do {
    p = StrPos(string,"{r}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='r';  p[2]='1'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{n}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='r';  p[2]='0'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{fc}");
    if ( p!=NULL )
    {    p[0]=(char)0x1D;  p[1]='V';  p[2]=66; p[3]='0'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{F1}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='!';  p[2]=16+1+32; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{F}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='!';  p[2]=17; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{f}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='!';  p[2]=0x01; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{B}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='E';  p[2]=1; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{b}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='E';  p[2]='0'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{E}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='E';  p[2]=1; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{e}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='E';  p[2]='0'; } else break;
  } while( p!=NULL );

  do {
    p = StrPos(string,"{fA}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='M';  p[2]='0'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{fB}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='M';  p[2]=1; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{fC}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='M';  p[2]=2; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{L}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='a';  p[2]='0'; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{C}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='a';  p[2]=1; } else break;
  } while( p!=NULL );
  do {
    p = StrPos(string,"{R}");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='a';  p[2]=2; } else break;
  } while( p!=NULL );

/*
  do {
    p = StrPos(string,"[P]");
    if ( p!=NULL )
    {    p[0]=(char)0x1B;  p[1]='a';  p[2]=2; } else break;
  } while( p!=NULL );
*/


  for ( p=string; *p!='\0'; p++ )
   if ( *p == (char)0xFF ) *p='\0';
 }
  unsigned long int wt;
//  return WriteFile( hCom,output.c_str(),output.Length(),&wt,NULL);
//ShowMessage( string );
  return WriteFile( hCom,string,output.Length(),&wt,NULL);
}
//---------------------------------------------------------------------------
HANDLE __fastcall TfTickets::ticket_AbrirPuerto(char *puerto)
{
  HANDLE hCom;

  hCom = CreateFile( puerto,
                     GENERIC_READ | GENERIC_WRITE,
                     0,    // comm devices must be opened w/exclusive-access
                     NULL, // no security attributes
                     OPEN_EXISTING, // comm devices must use OPEN_EXISTING
                     0,    // not overlapped I/O
                     NULL  // hTemplate must be NULL for comm devices
                     );

  if ( puerto[0]!='L' )
  if (hCom != INVALID_HANDLE_VALUE)
  {
    DCB dcb;
    // We will build on the current configuration, and skip setting the size
    // of the input and output buffers with SetupComm.
    if ( GetCommState(hCom, &dcb) )
    {

      // Fill in the DCB: baud=57,600 bps, 8 data bits, no parity, and 1 stop bit.
      dcb.BaudRate = CBR_9600;     // set the baud rate
      dcb.ByteSize = 8;             // data size, xmit, and rcv
      dcb.Parity = NOPARITY;        // no parity bit
      dcb.StopBits = ONESTOPBIT;    // one stop bit

      if ( !SetCommState(hCom, &dcb) )
              CloseHandle( hCom );
    }
  }
 return hCom;
}
//---------------------------------------------------------------------------
void __fastcall TfTickets::ticket_CerrarPuerto(void)
{
  CloseHandle( hCom );
}
//---------------------------------------------------------------------------

//###########################################################################


void __fastcall TfTickets::FormDestroy(TObject *Sender)
{
  delete ticketE;
  delete ticketS;
        
}
//---------------------------------------------------------------------------

