//---------------------------------------------------------------------------

#include <vcl.h>
#include <stdio.h>
#pragma hdrstop

#include <mmsystem.h>
// #include <vcl\Clipbrd.hpp>

#include "LEGO_COMM.h"
#include "TPropiedades.h"
#pragma package(smart_init)
#pragma link "LM2000"
//---------------------------------------------------------------------------

//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall Unit1::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
__fastcall CheckLEGOs::CheckLEGOs(bool CreateSuspended)
        : TThread(CreateSuspended)
{
 SetAntiPassBack(false);
 Lm2000 = new TLm2000(Propiedades->Owner);
 Lm2000->OnBuscaTarjeta = Lm2000BuscaTarjeta;
 Lm2000->OnVerboseMessage = Lm2000VerboseMessage;
 TbSession = new TSession(Propiedades->Owner);

}
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::SetDB( AnsiString Host, AnsiString Login, AnsiString PWD )
{
  // Asignamos los nuevos valores
  DB_host = Host;
  DB_login = Login;
  DB_pwd = PWD;

  TbSession->Active = false;
  TbSession->SessionName = "AccesosCAP";
  TbSession->Active = true;

  // Activamos los cambios
  TbCards = new TTable(Propiedades->Owner);
  TbCards->TableName = DB_host +  "\\datos\\Cards.db";
  TbCards->SessionName = "AccesosCAP";

  TbHistorial = new TTable(Propiedades->Owner);
  TbHistorial->TableName = DB_host +  "\\datos\\historial.db";
//  TbHistorial->BeforeOpen = TbHistorialBeforeOpen;
  TbHistorial->SessionName = "AccesosCAP";
  TbHistorial->Active = true;        // Tabla de eventos del sistema

  TbAccesos = new TTable(Propiedades->Owner);
  TbAccesos->TableName = DB_host +  "\\datos\\accesos.db";
  TbAccesos->SessionName = "AccesosCAP";
//  TbAccesos->BeforeOpen = TbAccesosBeforeOpen;
  TbAccesos->Active = true;        // Tabla de eventos del sistema
  crdDENTRO = TbAccesos->RecordCount;
  TbAccesos->Active = false;        // Tabla de eventos del sistema
  Propiedades->Ocupacion->Value = crdDENTRO;
}
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::SetPuerto( AnsiString pCOM )
{
 Puerto = pCOM;
}
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::SetDiasCortesia( int nDias )
{
 DiasDeCortesia = nDias;
}
//---------------------------------------------------------------------------
/*
void __fastcall CheckLEGOs::TbHistorialBeforeOpen(TDataSet *DataSet)
{
 if ( !FileExists( TbHistorial->TableName ) )
 {
	 // Usamos la propiedad FielDefs para definir
	 // las columnas que contendrá la tabla
     TbHistorial -> FieldDefs -> Clear();

  	 TbHistorial -> FieldDefs -> Add("id",       ftAutoInc,  0, false );
  	 TbHistorial -> FieldDefs -> Add("idCard",   ftInteger,  0, false );
  	 TbHistorial -> FieldDefs -> Add("fechaE",   ftDate,     0, false );
  	 TbHistorial -> FieldDefs -> Add("horaE",    ftTime,     0, false );
  	 TbHistorial -> FieldDefs -> Add("fechaS",   ftDate,     0, false );
  	 TbHistorial -> FieldDefs -> Add("horaS",    ftTime,     0, false );

     TbHistorial -> IndexDefs-> Clear();

	 TbHistorial->IndexDefs->Add("Primary",   "id", TIndexOptions() << ixPrimary << ixUnique);
	 TbHistorial->IndexDefs->Add("iAccesos", "idCard;fechaE;horaE", TIndexOptions() << ixCaseInsensitive );
         // Creamos la base...
	 TbHistorial -> CreateTable();
     Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + " :: Iniciando sistema por primera vez..." );
     Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + " :: Generación de ficheros auxiliares concluido" );
 }
}
*/
//---------------------------------------------------------------------------
/*
void __fastcall CheckLEGOs::TbAccesosBeforeOpen(TDataSet *DataSet)
{
 if ( !FileExists( TbAccesos->TableName ) )
 {
	 // Usamos la propiedad FielDefs para definir
	 // las columnas que contendrá la tabla
     TbAccesos -> FieldDefs -> Clear();

  	 TbAccesos -> FieldDefs -> Add("id",       ftAutoInc,  0, false );
  	 TbAccesos -> FieldDefs -> Add("idCard",   ftInteger,  0, false );
  	 TbAccesos -> FieldDefs -> Add("fechaE",   ftDate,     0, false );
  	 TbAccesos -> FieldDefs -> Add("horaE",    ftTime,     0, false );
  	 TbAccesos -> FieldDefs -> Add("puedeSalir", ftBoolean,     0, false );

     TbAccesos -> IndexDefs-> Clear();

	 TbAccesos->IndexDefs->Add("Primary",   "id", TIndexOptions() << ixPrimary << ixUnique);
	 TbAccesos->IndexDefs->Add("iAccesos", "idCard;fechaE;horaE", TIndexOptions() << ixCaseInsensitive );
         // Creamos la base...
	 TbAccesos -> CreateTable();
 }
}
*/
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::SetLegoID(int nLe, int *Le, int nLs, int *Ls)
{
 int i;

 nLEGOSe = nLe;
 if ( IDe ) delete [] IDe;
 IDe = new int[nLe];
 for ( i=0; i<nLe; i++ )
   IDe[i] = Le[i];


 nLEGOSs = nLs;
 if ( IDs ) delete [] IDs;
 IDs = new int[nLs];
 for ( i=0; i<nLs; i++ )
   IDs[i] = Ls[i];
}
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::Execute()
{
 char rcv[80]; AnsiString CB;
 int i,j=0;
/*
 // Forzamos el modo de trabajo
 POP pop = { 0, 0, 0, 1,    65535,    0,0,  0};
 CAB cab2 = { 0, 0, 0, 8, 0, 0, 0, 0 };
 Lm2000->ProgramOperationParameters( 1, &pop );
 Lm2000->SetCharsOnBand( 1, &cab2 );
*/
 Lm2000->CierraPuerto();
 Lm2000->AbrePuerto( Puerto.c_str() );

        //---- Place thread code here ----
        while( !Terminated )
        {
         //nothing;
         for ( i=0; i< nLEGOSe; i++ )
         {
          Propiedades->StatusBar1->Panels->Items[1]->Text = (j++);
          Lm2000->SimpleInterrogation( IDe[i], rcv );
          if ( rcv[5] == ':' )
                  Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + Format( " :: E(%03d)-%s", ARRAYOFCONST(( IDe[i], rcv )) ) );
         }

         if ( Terminated ) break;
/*
         if ( Clipboard()->HasFormat(CF_TEXT) )
         {
            if ( Clipboard()->AsText.SubString(1,7) == "JDsoft:" )
            {
             CB = Clipboard()->AsText;
             // Abrir barrera
             if ( CB[8] == 'O' )
                ShowMessage("Abrir barrera nº " + CB.SubString(9,CB.Length()) );
             // Cerrar barrera
             if ( CB[8] == 'C' )
                ShowMessage("Cerrar barrera nº " + CB.SubString(9,CB.Length()) );
             Clipboard()->Clear();
            }
         }
*/

         for ( i=0; i< nLEGOSs; i++ )
         {
          Propiedades->StatusBar1->Panels->Items[1]->Text = (j++);
          Lm2000->SimpleInterrogation( IDs[i], rcv );
          if ( rcv[5] == ':' )
                  Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + Format( " :: S(%03d)-%s", ARRAYOFCONST(( IDs[i], rcv )) ) );
         }

        }
 Lm2000->CierraPuerto();
}
//---------------------------------------------------------------------------
bool __fastcall CheckLEGOs::Lm2000VerboseMessage(AnsiString msg)
{
  if ( msg[3] != 'n' && msg[9] != ':' )
          Propiedades->StatusBar1->Panels->Items[0]->Text = msg;
  return true;
}
//---------------------------------------------------------------------------
/*
bool __fastcall CheckLEGOs::EsEntrada( int ID )
{
 bool dev = false;
 for ( int i=0; i<Propiedades->nLEGOSe; i++ )
 {
  if ( Propiedades->IDe[i] == ID )
  {
   dev = true;
   break;
  }
 }
 return dev;
}
*/
// El lector EXTERNO será siempre la SALIDA
#define EsEntrada( X ) (X & 0x0008)
//---------------------------------------------------------------------------
void __fastcall CheckLEGOs::SetAntiPassBack(bool AP)
{
  AntiPassBack = AP;
}
//---------------------------------------------------------------------------
bool __fastcall CheckLEGOs::RetiraPermisoSalida(void)
{
         TbAccesos->Active = true;

         TbAccesos->First();
         while( !TbAccesos->Eof )
         {
              // Si es abonado, denegamos su permiso a salir
           if ( (TbAccesos->FieldByName("idCard")->AsInteger & 0x0001)==0 )
           {
            if ( TbAccesos->FieldByName("PuedeSalir")->AsBoolean )
            {
             TbAccesos->Edit();
              TbAccesos->FieldByName("fechaE")->AsDateTime = TDateTime::CurrentDate();
              TbAccesos->FieldByName("horaE")->AsDateTime = TDateTime::CurrentTime();
              TbAccesos->FieldByName("PuedeSalir")->AsBoolean = false;
             TbAccesos->Post();
            }
           }
           TbAccesos->Next();
         }
         TbAccesos->Active = false;
}

bool __fastcall CheckLEGOs::Lm2000BuscaTarjeta(int ID, int FGA, int TPA,
      int CDA, int *TPR, int *PNR, char *message)
{
  bool dev = false;//, horaOK = true;
 *TPR = 0;
 *PNR = 0;


// Distinguimos entre ENTRAR y SALIR
// 27-mar-2002 Cambiada la funcion es entrada
// if ( EsEntrada( ID ) )
 if ( EsEntrada( FGA ) )
 {
   // E N T R A D A
/*
   // Comprueba si esta dentro del horario...
   if ( Propiedades->CheckHorario() )
   {
     sndPlaySound("snd\\fuera_de_hora.wav", SND_ASYNC | SND_FILENAME);
     sprintf( message, "-FUERA DE TIEMPOPase por caja" );
     dev = false;
   } else
*/
        {

          // Verificamos que el aforo no este lleno
          if ( crdDENTRO >= maxDENTRO )
          {
                   sndPlaySound("snd\\parking_lleno.wav", SND_ASYNC | SND_FILENAME);
                   sprintf( message, "-AFORO COMPLETO-por favor espere" );
                   dev = false;
          } else {
                  // El aforo NO ESTA LLENO
                  TbCards->Active = true;
//                  TbCards->Refresh();
                  // Buscamos si existe esa tarjeta...
                 dev = false; TbCards->First();
                 while( !TbCards->Eof )
                 {
                   if ( TbCards->FieldByName("idCard")->AsInteger == CDA )
                   { dev = true; break;} else TbCards->Next();
                 }

                  if ( dev )
                  {
                     TbAccesos->Active = true;        // Tabla de tarjetas dentro del complejo
                     dev = false; TbAccesos->First();
                     while( !TbAccesos->Eof )
                     {
                           if ( TbAccesos->FieldByName("idCard")->AsInteger == CDA )
                           { dev = true; break;} else TbAccesos->Next();
                     }
                     // Si ya ha entrado y no es un VIP
                     if ( dev && AntiPassBack && ! TbCards->FieldByName( "vip" ) -> AsBoolean )
                     {
                           sndPlaySound("snd\\card_acceso_denegado_antipassback.wav", SND_ASYNC | SND_FILENAME);
                           sprintf( message, "-YA ESTA DENTRO-" );
                           dev = false;
                     } else {
                           dev = false;
                           bool acceso = TbCards->FieldByName( "acceso" )->AsBoolean;
                           // Comprobamos los permisos
                           if ( acceso &&
                                TDateTime::CurrentDate() <= (TbCards->FieldByName( "fechaM" )->AsDateTime + DiasDeCortesia)
                              )
                           {
                                TbAccesos->Insert();
                                TbAccesos->FieldByName("idCard")->AsInteger = CDA;
                                TbAccesos->FieldByName("fechaE")->AsDateTime = TDateTime::CurrentDate();
                                TbAccesos->FieldByName("horaE")->AsDateTime = TDateTime::CurrentTime();
                                TbAccesos->FieldByName("PuedeSalir")->AsBoolean = true;
                                TbAccesos->Post();

                                crdDENTRO++;
                                Propiedades->Ocupacion->Value = crdDENTRO;
                                dev = true;
                                sndPlaySound("snd\\card_acceso_permitido_entrada.wav", SND_ASYNC | SND_FILENAME);
                           } else {
                                Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + Format( " :: V(%03d)-%d-%d-%d Valida Hasta: %s %s", ARRAYOFCONST(( ID, FGA, TPA, CDA, TbCards->FieldByName( "fechaM" )->AsString, acceso ? "CON ACCESO":"SIN ACCESO" )) ) );
                                sndPlaySound("snd\\card_acceso_denegado_entrada.wav", SND_ASYNC | SND_FILENAME);
                           }
                                sprintf( message, TbCards->FieldByName("msg")->AsString.c_str() );
                     }
                     TbAccesos->Active = false;        // Tabla de tarjetas dentro del complejo
                  } else {
                      sprintf( message, "-ACCESO DENEGADO-tarjeta no vale" );
                      Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + Format( " :: V(%03d)-%d-%d-%d", ARRAYOFCONST(( ID, FGA, TPA, CDA )) ) );
                      sndPlaySound("snd\\card_no_encontrado.wav", SND_ASYNC | SND_FILENAME);
                  }
                  TbCards->Active = false;
          }
   }
 } else {
  // S A L I D A
         TbAccesos->Active = true;        // Tabla de tarjetas dentro del complejo


                 dev = false; TbAccesos->First();
                 while( !TbAccesos->Eof )
                 {
                   if ( TbAccesos->FieldByName("idCard")->AsInteger == CDA )
                   { dev = true; break;} else TbAccesos->Next();
                 }

         if ( !dev && !AntiPassBack )
         {

                 TbCards->Active = true;
                 dev = false; TbCards->First();
                 while( !TbCards->Eof )
                 {
                   if ( TbCards->FieldByName("idCard")->AsInteger == CDA )
                   { dev = true; break;} else TbCards->Next();
                 }
                 TbCards->Active = false;

                 if (dev)
                 {
                  TbHistorial->Insert();
                  TbHistorial->FieldByName("idCard")->AsInteger = CDA;
                  TbHistorial->FieldByName("fechaS")->AsDateTime = TDateTime::CurrentDate();
                  TbHistorial->FieldByName("horaS")->AsDateTime = TDateTime::CurrentTime();
                  sprintf( message, "-ACCESO MULTIPLE PERMITIDO- Vuelva pronto" );
                  sndPlaySound("snd\\card_acceso_permitido_salida.wav", SND_ASYNC | SND_FILENAME);
                  dev = true;
                  TbAccesos->Active = false;        // Tabla de tarjetas dentro del complejo
                  return dev;
                 }
         }


         if ( dev )
         {
                if ( TbAccesos->FieldByName("PuedeSalir")->AsBoolean )
                {
                  // Movemos esta ficha al historial...
                  TbHistorial->Insert();
                  TbHistorial->FieldByName("idCard")->AsInteger = CDA;
                  TbHistorial->FieldByName("fechaE")->AsDateTime = TbAccesos->FieldByName("fechaE")->AsDateTime;
                  TbHistorial->FieldByName("horaE")->AsDateTime = TbAccesos->FieldByName("horaE")->AsDateTime;
                  TbHistorial->FieldByName("fechaS")->AsDateTime = TDateTime::CurrentDate();
                  TbHistorial->FieldByName("horaS")->AsDateTime = TDateTime::CurrentTime();
                  TbAccesos->Delete();
                  sprintf( message, "-ACCESO PERMITIDO- Vuelva pronto" );
                  sndPlaySound("snd\\card_acceso_permitido_salida.wav", SND_ASYNC | SND_FILENAME);
                  crdDENTRO--;
                  Propiedades->Ocupacion->Value = crdDENTRO;
                  dev = true;
                } else {
                  sprintf( message, "-ACCESO DENEGADO-Pase por caja" );
                  sndPlaySound("snd\\card_acceso_denegado_salida_pagar.wav", SND_ASYNC | SND_FILENAME);
                  dev = false;
                }
         } else {
                  sprintf( message, "-ACCESO DENEGADO- NO HA ENTRADO " );
                  sndPlaySound("snd\\card_acceso_denegado_salida.wav", SND_ASYNC | SND_FILENAME);
                  Propiedades->mHistorial->Lines->Insert( 0, (Now()).DateTimeString() + Format( " :: V(%03d)-%d-%d-%d", ARRAYOFCONST(( ID, FGA, TPA, CDA )) ) );
                  dev = false;
         }
         TbAccesos->Active = false;        // Tabla de tarjetas dentro del complejo
 }
 return dev;
}
//---------------------------------------------------------------------------

