//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "CtrlPPal.h"
#include "CtrlSocket.h"
#include "CtrlElemento.h"

//---------------------------------------------------------------------------
#pragma package(smart_init)

#define Blinking 600

//###########################################################################
//###########################################################################
//###########################################################################
//---------------------------------------------------------------------------
__fastcall TElemento::TElemento(TComponent* Owner)
    : TImage(Owner)
{
  NumElemento = 0;
  myIP="0.0.0.0";

  SurfaceIs = sfNone;

  BlinkCode = IP_OFF;                   // Intentando conectar con el TERMINAL
  StatusCode=  ERROR;                   // ERROR, aun no hemos conseguido conectar...

  Blink = new TTimer(this);             // Establecemos el timer, que mostrará las advertencias
  Blink->OnTimer  = OnBlink;            // visuales de estado del componente.
  Blink->Interval = Blinking;                // Inicialmente activo, con la advertencia IP_QUERY
  Blink->Enabled = true;

  Revisor = new TTimer(this);           // Este timer, se encargará de comunicar el estado OFF
  Revisor->OnTimer  = OnRevisor;          // al TERMINAL-DOG, cuando proceda. ( Finalizado su tiempo ).
  Revisor->Interval = 0;
  Revisor->Enabled = false;
  PideMasTiempo = false;
}
//---------------------------------------------------------------------------
__fastcall TElemento::~TElemento()
{
 delete Blink;
 delete Revisor;
}
//---------------------------------------------------------------------------
void __fastcall TElemento::SetElemento( int Elemento, AnsiString IP, AnsiString Name )
{
 if ( ! IP.IsEmpty() && IP.Length() >= 7 )
                                    myIP = IP;
 NumElemento = Elemento;
 myName = Name;
 if ( !CtrlPPal->ServerHook )
     RefreshElement();
}
//---------------------------------------------------------------------------
void __fastcall TElemento::RefreshElement(void)
{
 BlinkCode = IP_QUERY;
 StatusCode = ERROR;
// Blink->Enabled = true;
 Blink->Interval = Blinking;

 //////// Vemos si el terminal esta activo ///////////////////////////////////
        ThreadSocket *MySocket;
        MySocket = (ThreadSocket *)CtrlPPal->GetThread();
        MySocket->SetSocket( myIP, 5432 );
        MySocket->OWNER_Element = this;
        MySocket->CtrlCOP = QueryTIME;
        MySocket->CtrlTiempo = TDateTime::CurrentTime();
        MySocket->Resume();
 ////////                                 ///////////////////////////////////
}
//---------------------------------------------------------------------------
void __fastcall TElemento::HistoricoTermON( TDateTime CtrlTiempo )
{
  bool UsaBono = (Precio == -1);
  if ( UsaBono ) Precio = 0;
  if ( PideMasTiempo )
  {
   ImporteAcumulado += Precio;
   if ( CtrlTiempo > TiempoPedido ) CtrlTiempo = TiempoPedido;
  } else {
   ImporteAcumulado = Precio;
  }

  // Insertamos en el historial de usos, la activación del terminal...
  CtrlPPal->TbHistorial -> InsertRecord( ARRAYOFCONST(( NumElemento,
                                      (Variant)TiempoComienzo,
                                      (Variant)CtrlTiempo, idc, idtc, Precio )) );
  CtrlPPal->TbHistorial -> FlushBuffers();
  // Descontamos al cliente su tiempo del bono...
  if ( UsaBono )
  {
                TBookmark SavePlace;
                // get a bookmark so that we can return to the same record
                SavePlace = CtrlPPal->TbPersonas->GetBookmark();

          if ( CtrlPPal->TbPersonas->Locate( "CodCliente1", idc, TLocateOptions() << loCaseInsensitive) )
          {
           unsigned short Hour, Min, Sec, MSec;
           CtrlTiempo.DecodeTime( &Hour, &Min, &Sec, &MSec );

           NCliente = CtrlPPal->TbPersonas->FieldByName("Nombre")->AsString + " " + CtrlPPal->TbPersonas->FieldByName("Apellidos")->AsString;
           CtrlPPal->TbPersonas->Edit();
           if ( CtrlPPal->TbPersonas->FieldByName("TiempoM")->AsInteger < Min )
           {
                   CtrlPPal->TbPersonas->FieldByName("TiempoH")->AsInteger = CtrlPPal->TbPersonas->FieldByName("TiempoH")->AsInteger - Hour -1;
                   CtrlPPal->TbPersonas->FieldByName("TiempoM")->AsInteger = (CtrlPPal->TbPersonas->FieldByName("TiempoM")->AsInteger +60 - Min);
           } else {
                   CtrlPPal->TbPersonas->FieldByName("TiempoH")->AsInteger = CtrlPPal->TbPersonas->FieldByName("TiempoH")->AsInteger - Hour;
                   CtrlPPal->TbPersonas->FieldByName("TiempoM")->AsInteger = CtrlPPal->TbPersonas->FieldByName("TiempoM")->AsInteger - Min;
           }

           CtrlPPal->TbPersonas->FieldByName("FModif")->AsDateTime = TDateTime::CurrentDateTime();
           CtrlPPal->TbPersonas->Post();
           CtrlPPal->TbPersonas->FlushBuffers();
          } else {
           NCliente = "## No ENCONTRADO ##";
          }
                  // Move back to the bookmark
                  CtrlPPal->TbPersonas->GotoBookmark(SavePlace);
                  CtrlPPal->TbPersonas->FreeBookmark(SavePlace);
  }
}
//---------------------------------------------------------------------------
void __fastcall TElemento::SetActiveTime( TDateTime Tiempo, int L_idc, int L_idtc, Currency L_Precio )
{
 idc = L_idc; idtc = L_idtc; Precio = L_Precio;
 TDateTime Queda = TiempoRestante();
 BlinkCode = IP_QUERY;
 StatusCode = ERROR;
// Blink->Enabled = true;
 Blink->Interval = Blinking;

 if ( Revisor->Enabled )
 {
  PideMasTiempo = true;
  Revisor->Enabled = false;
  TiempoComienzo = TDateTime::CurrentDateTime() + Queda;
 } else {
  PideMasTiempo = false;
  TiempoComienzo = TDateTime::CurrentDateTime();
 }
 TiempoPedido = Tiempo;

 ThreadSocket *MySocket;
 MySocket = (ThreadSocket *)CtrlPPal->GetThread();
 MySocket->SetSocket( myIP, 5432 );
 MySocket->CtrlCOP = SettingSTATUS;
 MySocket->OWNER_Element = this;
 if ( PideMasTiempo )
  MySocket->CtrlTiempo = TiempoPedido + Queda;
 else
  MySocket->CtrlTiempo = TiempoPedido;
 MySocket->CtrlState = true;
 MySocket->Resume();

 unsigned short  hour,  min,  sec,  msec;
 if ( PideMasTiempo ) Tiempo = Tiempo + Queda;
 Tiempo.DecodeTime( &hour, &min, &sec, &msec );
 Revisor->Interval = msec + ( sec + ( (min+0) + hour*60 )*60 )*1000 ;
 Revisor->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TElemento::OnBlink(TObject *Sender)
{

 ultImagen = !ultImagen;
 // Mostrar parpadeo según corresponda...
 switch ( BlinkCode )
 {
  case IP_OFF:
     if ( SurfaceIs != sfRoja )
     {
      SurfaceIs = sfRoja;
      Picture = CtrlPPal->iElemento2->Picture;
      WriteMyName();
     }
    if ( ultImagen )
      Canvas->Draw( 17, 3, CtrlPPal->iElemento3->Picture->Graphic );
    else
      Canvas->FillRect(Rect(17,4,60,48));
    break;
  case IP_QUERY:
     if ( SurfaceIs != sfAzul )
     {
      SurfaceIs = sfAzul;
      Picture = CtrlPPal->iElementoV->Picture;
      WriteMyName();
     }
    if ( ultImagen )
      Canvas->Draw( 17, 3, CtrlPPal->iElemento4->Picture->Graphic );
    else
      Canvas->FillRect(Rect(17,4,60,48));
    break;
  case NONE:
  default:
      ShowElementInfo();
    break;
 }
}
//---------------------------------------------------------------------------
void __fastcall TElemento::OnRevisor(TObject *Sender)
{
  ForcedTimeOut();
//  ShowMessage(
  CtrlPPal->Memo1->Lines->Insert( 0, (Now()).DateTimeString() + Format( " Terminal %d. Fin de Tiempo. :_)", ARRAYOFCONST((NumElemento))));

  Revisor->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall TElemento::ForcedTimeOut(void)
{
    Revisor->Enabled = false;
    StatusCode = ERROR;                     // Estamos en proceso de COMPROBACION / ERROR
    BlinkCode = IP_QUERY;                   // --- INTENTANDO COMUNICAR --
//    Blink->Enabled = true;                  // Activamos el parpadeo
 Blink->Interval = Blinking;

    /// ENVIAMOS EL MENSAJE...
    ThreadSocket *MySocket;
    MySocket = (ThreadSocket *)CtrlPPal->GetThread();
    MySocket->SetSocket( myIP, 5432 );
    MySocket->CtrlCOP = SettingSTATUS;
    MySocket->OWNER_Element = this;
    MySocket->CtrlState = false;
    MySocket->Resume();

  //################################################################################################
  TBookmark SavePlace;
  SavePlace = CtrlPPal->TbElementosCFG->GetBookmark();
  if ( CtrlPPal->TbElementosCFG -> Locate( "NumElement", NumElemento, TLocateOptions() << loCaseInsensitive ) )
  {
                if ( CtrlPPal->TbElementosCFG->FieldByName( "Activo" )->AsBoolean )
                {
                    CtrlPPal->TbElementosCFG->Edit();
                    CtrlPPal->TbElementosCFG->FieldByName( "Tiempo" )->AsDateTime = EncodeTime( 0, 0, 0, 0 );
                    CtrlPPal->TbElementosCFG->FieldByName( "Activo" )->AsBoolean = false;
                    CtrlPPal->TbElementosCFG->Post();
                }
  }
  CtrlPPal->TbElementosCFG->GotoBookmark(SavePlace);
  CtrlPPal->TbElementosCFG->FreeBookmark(SavePlace);
  //################################################################################################
}
//---------------------------------------------------------------------------
void __fastcall TElemento::MouseDown(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
 Picture = CtrlPPal->iElemento2->Picture;
 if ( CtrlPPal->ChangePositionEnabled )
 {
  if ( Button == mbLeft )
     ElementoAnclado = true;
  faElmX = X;
  faElmY = Y;
 }

}
//---------------------------------------------------------------------------
void __fastcall TElemento::MouseMove(TShiftState Shift, int X, int Y)
{
 if ( CtrlPPal->ChangePositionEnabled )
 {
     if ( ElementoAnclado )
     {
      POINT MousePos;
      GetCursorPos(&MousePos);
      Left = MousePos.x - CtrlPPal->Left - CtrlPPal->Pizarra->Left - faElmX;
      Top  = MousePos.y - CtrlPPal->Top  - CtrlPPal->Pizarra->Top  - faElmY;
     }
 }
}
//---------------------------------------------------------------------------
void __fastcall TElemento::MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y)
{
 // (Mover)
 if ( Button == mbLeft )
 {
   if ( CtrlPPal->ChangePositionEnabled )
   {
     ElementoAnclado = false;
     if ( Left <= 0 ) Left = 0;
     if ( Top  <= 0 ) Top  = 0;

     // ##########################################################################################
     if ( CtrlPPal->TbElementosCFG -> Locate( "NumElement", NumElemento, TLocateOptions() << loCaseInsensitive ) )
       {
        CtrlPPal->TbElementosCFG -> Edit();
        CtrlPPal->TbElementosCFG -> FieldByName("PosX") -> AsInteger = Left;
        CtrlPPal->TbElementosCFG -> FieldByName("PosY") -> AsInteger = Top;
        CtrlPPal->TbElementosCFG -> Post();
       }
     // ##########################################################################################
   }
 }
 SurfaceIs = sfNone;
 ShowElementInfo();
}
//---------------------------------------------------------------------------
// TiempoInicio --> Tiempo que queda hasta la desconexión
void __fastcall TElemento::ClientTimeIs( double Tiempo, double TiempoInicio )
{
  BlinkCode = NONE;
//  Blink->Enabled = false;
 Blink->Interval = 60000;

  if ( Tiempo <= 0 )
  {
      StatusCode = FREE;
      Revisor->Enabled = false;
  } else {
      if ( StatusCode !=WORKING || (double)TiempoPedido < Tiempo )
      {
         TiempoComienzo = ( TDateTime::CurrentTime() - (Tiempo - TiempoInicio) );
//         TiempoComienzo = TiempoInicio;
         TiempoPedido = Tiempo;

         unsigned short  hour,  min,  sec,  msec;
         RTiempoRestante = TiempoInicio;
         RTiempoRestante.DecodeTime( &hour, &min, &sec, &msec );

         Revisor->Enabled = false;
         Revisor->Interval = msec + ( sec + ( (min+0) + hour*60 )*60 )*1000 ;
         Revisor->Enabled = true;
      }
      StatusCode = WORKING;
  }

  ShowElementInfo();
}
//---------------------------------------------------------------------------
void __fastcall TElemento::ShowElementInfo( void )
{
  if ( StatusCode != ERROR )
  {
//   Picture = StatusCode != FREE ? CtrlPPal->iElementoV->Picture : CtrlPPal->iElemento5->Picture;
   Picture = CtrlPPal->iElementoV->Picture;
   WriteMyName();

   unsigned short h, m, s, ms; int w;
   AnsiString sOUT;

   Canvas->Font->Size = 12;
   sOUT = "# " + AnsiString( NumElemento ) + " #";   w = ( 44 - Canvas->TextWidth( sOUT ) ) / 2;

   // En caso de estar activo el terminal
   if ( StatusCode == WORKING )
   {
     Canvas->Font->Color = clRed;       /*Nombre del Terminal*/   Canvas->TextOut( 17+w, 3, sOUT  );

     Canvas->Font->Color = clBlue;     Canvas->Font->Size = 10;

     // Hora en la que inicia la sesión.
     TiempoComienzo.DecodeTime( &h, &m, &s, &ms );
     sOUT = Format( "%02d:%02d", ARRAYOFCONST(( h, m )) );
     w = ( 44 - Canvas->TextWidth( sOUT ) ) / 2;
     Canvas->TextOut( 17+w, 22, sOUT );
     // Tiempo de juego que le queda
     TDateTime Queda;
     Queda = TiempoRestante();//TiempoPedido + TiempoComienzo - TDateTime::CurrentTime();
     Queda.DecodeTime( &h, &m, &s, &ms );
     Canvas->TextOut( 17, 35, Format( "R: %02d:%02d", ARRAYOFCONST(( h, (m+1) ))) );
/*
     // Tiempo de juego que le fue asignado
     (TbElementosCFG->FieldByName( "Tiempo" )->AsDateTime).DecodeTime( &h, &m, &s, &ms );
     E->Canvas->TextOut( 17, 40, Format( "((( %02d:%02d )))", ARRAYOFCONST(( h, m ))) );
*/
   } else {
       Canvas->Font->Color = clBlue;
       // Nombre/Número del terminal
       Canvas->TextOut( 17+w, 3, sOUT );

     // El terminal esta libre
     Canvas->Font->Color = clGreen;
     Canvas->TextOut( 15, 25, "LIBRE" );
   }
  }
}
//---------------------------------------------------------------------------
void __fastcall TElemento::CerrarWindows( void )
{
  StatusCode = ERROR;                     // Estamos en proceso de COMPROBACION / ERROR
  BlinkCode = IP_QUERY;                   // --- INTENTANDO COMUNICAR --
//  Blink->Enabled = true;                  // Activamos el parpadeo  /// ENVIAMOS EL MENSAJE...
 Blink->Interval = Blinking;

  ThreadSocket *MySocket;
  MySocket = (ThreadSocket *)CtrlPPal->GetThread();
  MySocket->SetSocket( myIP, 5432 );
  MySocket->CtrlCOP   = CloseWINDOWS;
  MySocket->CtrlState = CloseWINDOWS;
  MySocket->Resume();

  // Actualizamos el historial
  CtrlPPal->TbHistorial -> InsertRecord( ARRAYOFCONST(( NumElemento,
                                      (Variant)TDateTime::CurrentDateTime(),
                                      (Variant)TiempoRestante(), 0, 999, 0 )) );

}
//---------------------------------------------------------------------------
void __fastcall TElemento::EnviarListasAppl( void )
{
/*
  StatusCode = ERROR;                     // Estamos en proceso de COMPROBACION / ERROR
  BlinkCode = IP_QUERY;                   // --- INTENTANDO COMUNICAR --
  Blink->Interval = Blinking;
*/

  ThreadSocket *MySocket;
  MySocket = (ThreadSocket *)CtrlPPal->GetThread();
  MySocket->SetSocket( myIP, 5432 );
  MySocket->CtrlCOP   = sendLIST;
  MySocket->CtrlState = sendLIST;
  MySocket->Resume();

  // Actualizamos el historial
  CtrlPPal->TbHistorial -> InsertRecord( ARRAYOFCONST(( NumElemento,
                                      (Variant)TDateTime::CurrentDateTime(),
                                      (Variant)TiempoRestante(), 0, 997, 0 )) );

}
//---------------------------------------------------------------------------
void __fastcall TElemento::WriteMyName( void )
{
  int W;

  Canvas->Font->Color = clRed;
  Canvas->Font->Style = Canvas->Font->Style << fsBold;
  Canvas->Font->Size = 10;
  W = ( 77 - Canvas->TextWidth( myName ) ) / 2;
  Canvas->TextOut( W, 64, myName );
  Canvas->Font->Style = Canvas->Font->Style >> fsBold;
}
//---------------------------------------------------------------------------
TDateTime __fastcall TElemento::TiempoRestante(void)
{
 return TiempoPedido + TiempoComienzo - TDateTime::CurrentTime();
}
//---------------------------------------------------------------------------
TDateTime __fastcall TElemento::TiempoInicio(void)
{
 return TiempoComienzo;
}
//---------------------------------------------------------------------------

