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

#include <vcl.h>
#pragma hdrstop

#include <Math.hpp>
#include <inifiles.hpp>

#include "main.h"
#include "splash.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "VidGrab"
#pragma link "ZAbstractDataset"
#pragma link "ZAbstractRODataset"
#pragma link "ZConnection"
#pragma link "ZDataset"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
 currentUID = 0;
 txt0->Caption = "";

 camPreviewStarted = false;
 pFondoAPP = new TPicture();

 AnsiString filename;

 Randomize();
 filename = ExtractFileDir( Application->ExeName )+"\\bg\\bg0"+AnsiString(RandomRange(1,7))+".jpg";
 if ( FileExists(filename) )
        pFondoAPP->LoadFromFile(filename);

 Color = clBlack;
 if ( pFondoAPP->Graphic && !pFondoAPP->Graphic->Empty )
 {
        Image1->Picture->Assign(pFondoAPP);
        Image1->Top = (this->Width-pFondoAPP->Width)/2;
        Image1->Left = (this->Height-pFondoAPP->Height)/2;
        Image1->Width = pFondoAPP->Width;//Min(this->Width,pFondoAPP->Width);
        Image1->Height = pFondoAPP->Height;//Min(this->Height,pFondoAPP->Height);

//          Canvas->Draw( (this->Width-pFondoAPP->Width)/2,(this->Height-pFondoAPP->Height)/2,pFondoAPP->Graphic);
 }



 VideoGrabber1->Visible = false;
// VideoGrabber1->StartPreview();
 if ( splashScreen )
 {
   splashScreen->loaded_main = true;
   if ( splashScreen->timeOut ) splashScreen->Close();
 }

 initDB();

}
//---------------------------------------------------------------------------
void __fastcall TForm1::initDB(void)
{
 TIniFile *ini;
 ini = new TIniFile( ExtractFileDir( Application->ExeName ) + "\\controlHorario.INI" );


 ZConnection1->HostName = ini->ReadString( "DB", "Host", "localhost" );
 ZConnection1->Database = ini->ReadString( "DB", "DB", "controlHorario" );
 ZConnection1->LoginPrompt = ini->ReadBool( "DB", "LoginPrompt", false );
 ZConnection1->User = ini->ReadString( "DB", "Login", "controlHorario_user" );
 ZConnection1->Password = ini->ReadString( "DB", "Password", "controlHorario_pass" );
 ZConnection1->Port = ini->ReadInteger( "DB", "Port", 3306 );
 ZConnection1->Protocol = ini->ReadString( "DB", "protocol", "mysql-4.1" );

 try {
         ZConnection1->Connect();
 } catch(...) {
        // nothing
        ZConnection1AfterDisconnect(NULL);
 }
 
 delete ini;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
/*
 Color = clBlack;
 if ( pFondoAPP->Graphic && !pFondoAPP->Graphic->Empty )
          Canvas->Draw( (this->Width-pFondoAPP->Width)/2,(this->Height-pFondoAPP->Height)/2,pFondoAPP->Graphic);
*/
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormResize(TObject *Sender)
{

 /* Recorrer todos los elementos y reubicarlos...
 */
 int i,offsetX, offsetY;
 if ( this->Width > 792 ) offsetX = (this->Width-792)/2;  else offsetX = 0;
 if ( this->Width > 566 ) offsetY = (this->Height-566)/2; else offsetY = 0;
 Left = 0;
 Top = 0;

 TComponent *Temp;
 for ( i=this->ComponentCount-1; i>=0; i-- )
 {
    Temp = this->Components[i];
    // only move components that are not controls
    if (dynamic_cast<TControl *>(Temp) != NULL)
    {
      if ( Temp!=clock )
      {
              ((TControl *)Temp)->Left += offsetX;
              ((TControl *)Temp)->Top += offsetY;
      }
    }
 }



}
//---------------------------------------------------------------------------
/*
  if ( camPreviewStarted )
        VideoGrabber1->CaptureFrameTo (fc_TBitmap, "");
*/
//---------------------------------------------------------------------------

void __fastcall TForm1::VideoGrabber1FrameCaptureCompleted(TObject *Sender,
      const TFrameData &FrameData, TFrameCaptureDest DestType,
      AnsiString FileName, bool Success)
{
//   Graphics::TBitmap *Frame_Bitmap;


   switch (DestType) {
      case fc_BmpFile:
//         Memo1->Lines->Add (FileName + " created");
      break;

      case fc_JpegFile:
//         Memo1->Lines->Add (FileName + " created");
      break;

      case fc_TBitmap:
//           Frame_Bitmap = (Graphics::TBitmap*) FrameData;

          //Requires "jpeg.hpp" to be included in the source file
          TJPEGImage *jp = new TJPEGImage();
          try
          {
            jp->Assign(FrameData.Bitmap);
            jp->SaveToFile("cam_"+AnsiString(FrameData.FrameNumber)+".jpg");
          }
          __finally
          {
            delete jp;
          }


      break;
  }

}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  VideoGrabber1->StopPreview();
  if ( VideoGrabber1->Busy ) CanClose = false;        
}
//---------------------------------------------------------------------------


void __fastcall TForm1::VideoGrabber1PreviewStarted(TObject *Sender)
{
  camPreviewStarted = true;
  VideoGrabber1->Visible = true;        
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  clock->Caption = (TDateTime::CurrentTime()).TimeString();
  if ( !ZConnection1->Connected && nextTry>=0 )
  {
        if ( nextTry==0 )
        {
                try {
                        nextTry = -1;
                        ZConnection1->Connect();
                } catch(...) {
                        // nothing
                        ZConnection1AfterDisconnect(NULL);
                }
        } else {
                txt0->Caption = "ERROR CONECTANDO DB ("+AnsiString(nextTry)+" sg.)";
                nextTry--;
        }
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
  if ( !ZConnection1->Connected ) return;

  if ( Key==VK_RETURN )
  {
        if ( barCode01->Caption.Length() != 12 )
        {
                showText("Error, código no válido","VUELVA A PASAR TARJETAS");
                currentUID = 0;
        } else {
          int prefijo = barCode01->Caption.SubString(1,2).ToIntDef(0);
          int codigo = barCode01->Caption.SubString(3,10).ToIntDef(0); 
          switch ( prefijo )
          {
                // Códigos de tarjetas
                case 05:
                        if ( existeUsuario( codigo, &ultimoEstado, &currentUser ) )
                        {
                          if ( ultimoEstado=='E' )
                          {
                                showText(currentUser,"Pase orden de Trabajo ó Tarjeta de Salida");
                                currentUID = codigo;
                          } else {
                                if ( currentUID == codigo )
                                {
                                  picarEntradaUsuario( codigo );
                                  showText("ENTRADA CORRECTA", "ENTRADA CORRECTA");
                                  currentUID = 0;
                                } else {
                                  showText(currentUser, "Vuelva a pasar Tarjeta de USUARIO");
                                  currentUID = codigo;
                                }
                          }
                        } else {
                                showText("Usuario inactivo","TARJETA NO VÁLIDA");
                                currentUID = 0;
                        }
                        break;
                // Orden de trabajo
                case 50:
                        if ( currentUID > 0 && ultimoEstado=='E' )
                        {
                          // Comprobamos que el operario no tenga abierta ninguna orden de trabajo
                          int oT = tieneOrdenTrabajoAbierta( currentUID );
                          if ( oT>0 && oT!=codigo )
                          {
                                showText("ERROR ORDEN de trabajo en curso","CIERRE LA ORDEN de trabajo número "+AnsiString(oT));
                                currentUID = 0;
                          } else {
                                AnsiString estado;

                                if ( existeOrdenTrabajo( codigo, currentUID, &estado ) )
                                {
                                  if ( estado=="A" )
                                  {
                                    cierraTrabajo( currentUID, codigo );
                                    showText(currentUser,"CERRADA ORDEN de trabajo");
                                  } else {
                                    iniciaTrabajo( currentUID, codigo );
                                    showText(currentUser,"INICIADA ORDEN de trabajo");
                                  }
                                } else {
                                  showText("ORDEN de trabajo no activa","ó ASIGNADA A OTRO EMPLEADO");
                                }
                                currentUID = 0;
                          }
                        }
                        break;

                // Comandos para el sistema
                case 99:
                        switch( codigo )
                        {
                                // Salida de usuario
                                case 1:
                                        if ( currentUID>0 && ultimoEstado=='E' )
                                        {
                                                cierraTrabajos( currentUID );
                                                picarSalidaUsuario( currentUID );
                                                showText(currentUser,"SALIDA CORRECTA");
                                        } else
                                                showText("Pase primero tarjeta de usuario","USUARIO SIN IDENTIFICAR");
                                        break;


                                // Shutdown (Apagar el sistema)
                                case 1010:
                                        break;
                                // Cerrar el programa
                                case 1005:
                                        Close();
                                        break;
                                // Minimizar el programa
                                case 2:
                                        Application->Minimize();
                                        break;
                                default:
                                        showText("Error, código no válido","VUELVA A PASAR TARJETAS");
                        }
                        currentUID = 0;
                        break;
                case 0:
                default:
                        showText("Error, código no válido","VUELVA A PASAR TARJETAS");
                        currentUID = 0;
                        break;
          }
        }

        barCode01->Caption = "";
        barCode02->Caption = "";
  } else {     
        if ( barCode01->Caption.Length() > 12 )
        {
                barCode01->Caption = "";
                barCode02->Caption = "";
        }
        barCode01->Caption = barCode01->Caption + AnsiString(Key);
        barCode02->Caption = barCode01->Caption;
  }

}
//---------------------------------------------------------------------------

void __fastcall TForm1::showText(AnsiString txt,AnsiString txtAux)
{
   Timer2->Enabled = false;

   txt0->Caption = txt;
   txt1->Caption = txtAux;
   Timer2->Enabled = true;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Timer2Timer(TObject *Sender)
{
   txt0->Caption = "";
   txt1->Caption = "";
   Timer2->Enabled = false;
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::existeUsuario( int uid, char *ultimoEstado, AnsiString *user  )
{
  bool dev;

  // Comprobamos que exista el usuario
  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("SELECT CONCAT_WS(' ',Nombre,Apellidos) operario FROM personas WHERE id="+AnsiString(uid));
  ZQuery1->Active = ZQuery1->Connection->Connected;
  if ( ZQuery1->RecordCount>0 )
  {
        *user = ZQuery1->FieldByName("operario")->AsString;
        showText( ZQuery1->FieldByName("operario")->AsString,"" );

        // Rescatamos el último estado de este usuario
        ZQuery1->SQL->Clear();
        ZQuery1->SQL->Add("SELECT flag FROM controlHorario_accesos WHERE idp="+AnsiString(uid)+" AND modid=0 ORDER BY id DESC LIMIT 0,1");
        ZQuery1->Active = ZQuery1->Connection->Connected;
        if ( ZQuery1->RecordCount>0 && ZQuery1->FieldByName("flag")->AsString != "S" )
          *ultimoEstado = 'E';
        else
          *ultimoEstado = 'S';

        dev = true;
  } else
        dev = false;

  return dev;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::picarEntradaUsuario( int uid )
{
  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_accesos (timestamp,idp,evento,flag,modid,modlnk) VALUES (UNIX_TIMESTAMP(),"+AnsiString(uid)+",0,'E',0,0)");
  ZQuery1->ExecSQL();
}
//---------------------------------------------------------------------------
int __fastcall TForm1::tieneOrdenTrabajoAbierta( int uid )
{
  int oT = 0;

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("SELECT idpp FROM controlHorario_pProduccionPer WHERE estado='A' AND idp="+AnsiString(uid));
  ZQuery1->Active = ZQuery1->Connection->Connected;

  if ( ZQuery1->RecordCount> 0 )
        oT = ZQuery1->FieldByName("idpp")->AsInteger;

  return oT;
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::existeOrdenTrabajo( int orden, int uid, AnsiString *estado )
{
  bool dev;

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("SELECT estado FROM controlHorario_pProduccionPer WHERE idpp="+AnsiString(orden)+" AND idp="+AnsiString(uid));
  ZQuery1->Active = ZQuery1->Connection->Connected;

  if ( ZQuery1->RecordCount>0 )
  {
        *estado = ZQuery1->FieldByName("estado")->AsString;
        dev = true;
  } else {
        dev = false;
  }

  return dev;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cierraTrabajo( int uid, int orden )
{
  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("UPDATE controlHorario_pProduccionPer SET estado='C' WHERE idpp="+AnsiString(orden)+" AND idp="+AnsiString(uid));
  ZQuery1->ExecSQL();

        // Si no hay mas operarios trabajando en el parte
        ZQuery2->SQL->Clear();
        ZQuery2->SQL->Add("SELECT COUNT(*) c FROM controlHorario_pProduccionPer WHERE estado='A' AND idpp="+AnsiString(orden));
        ZQuery2->Active = ZQuery2->Connection->Connected;

        // ...lo damos por concluido
        if ( ZQuery2->FieldByName("c")->AsInteger<=0 )
        {
                ZQuery2->SQL->Clear();
                ZQuery2->SQL->Add("UPDATE controlHorario_pProduccionCab SET estado='P' WHERE id="+AnsiString(orden) );
                ZQuery2->ExecSQL();
        }

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_accesos (timestamp,idp,evento,flag,modid,modlnk) VALUES (UNIX_TIMESTAMP(),"+AnsiString(uid)+",0,'S',36,"+AnsiString(orden)+")");
  ZQuery1->ExecSQL();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::iniciaTrabajo( int uid, int orden )
{
  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("UPDATE controlHorario_pProduccionCab SET estado='A' WHERE id="+AnsiString(orden));
  ZQuery1->ExecSQL();

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_pProduccionPer (idpp,idp,estado) VALUE ("+AnsiString(orden)+","+AnsiString(uid)+",'A') ON DUPLICATE KEY UPDATE estado='A'");
  ZQuery1->ExecSQL();

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_accesos (timestamp,idp,evento,flag,modid,modlnk) VALUES (UNIX_TIMESTAMP(),"+AnsiString(uid)+",0,'E',36,"+AnsiString(orden)+")");
  ZQuery1->ExecSQL();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::cierraTrabajos( int uid )
{
  int idpp;

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_accesos (timestamp,idp,evento,flag,modid,modlnk) ");
  ZQuery1->SQL->Add(" SELECT UNIX_TIMESTAMP(),"+AnsiString(uid)+",0,'S',36,p.idpp ");
  ZQuery1->SQL->Add(" FROM controlHorario_pProduccionPer p WHERE p.estado='A' AND p.idp="+AnsiString(uid));
  ZQuery1->ExecSQL();

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("SELECT idpp FROM controlHorario_pProduccionPer WHERE estado='A' AND idp="+AnsiString(uid));
  ZQuery1->Active = ZQuery1->Connection->Connected;

  ZQuery1->First();
  while( !ZQuery1->Eof )
  {
        idpp = ZQuery1->FieldByName("idpp")->AsInteger;
        
        // Fijamos el estado del operario en este parte a cerrado
        ZQuery2->SQL->Clear();
        ZQuery2->SQL->Add("UPDATE controlHorario_pProduccionPer SET estado='C' WHERE idpp="+AnsiString(idpp)+" AND idp="+AnsiString(uid));
        ZQuery2->ExecSQL();

        // Si no hay mas operarios trabajando en el parte
        ZQuery2->SQL->Clear();
        ZQuery2->SQL->Add("SELECT COUNT(*) c FROM controlHorario_pProduccionPer WHERE estado='A' AND idpp="+AnsiString(idpp));
        ZQuery2->Active = ZQuery2->Connection->Connected;

        // ...lo damos por concluido
        if ( ZQuery2->FieldByName("c")->AsInteger<=0 )
        {
                ZQuery2->SQL->Clear();
                ZQuery2->SQL->Add("UPDATE controlHorario_pProduccionCab SET estado='P' WHERE id="+AnsiString(idpp) );
                ZQuery2->ExecSQL();
        }

        ZQuery1->Next();
  }

  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("UPDATE controlHorario_pProduccionPer SET estado='C' WHERE estado='A' AND idp="+AnsiString(uid));
  ZQuery1->ExecSQL();




}
//---------------------------------------------------------------------------
void __fastcall TForm1::picarSalidaUsuario( int uid )
{
  ZQuery1->SQL->Clear();
  ZQuery1->SQL->Add("INSERT INTO controlHorario_accesos (timestamp,idp,evento,flag,modid,modlnk) VALUES (UNIX_TIMESTAMP(),"+AnsiString(uid)+",0,'S',0,0)");
  ZQuery1->ExecSQL();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ZConnection1AfterDisconnect(TObject *Sender)
{
        // Reintentar conexión en 20sg
        nextTry = 20;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ZConnection1BeforeConnect(TObject *Sender)
{
        txt0->Caption = "CONECTANDO A RED. Por favor, espere...";
        txt0->Caption = ";-)";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ZConnection1AfterConnect(TObject *Sender)
{
        txt0->Caption = "";
        txt1->Caption = "";
}
//---------------------------------------------------------------------------

