//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "WatchdogSignal.h"
#include "Train_Control.h"
#include "Setup_Control.h"
#include "Debug_Controls.h"
#include "Comm_Thread.h"
#include "Watchdog_Thread.h"
#include "Clipbrd.hpp"

//---------------------------------------------------------------------------
// Workaround for SetLayeredWindowAttributes() to make transparent windows
extern lpfnSetLayeredWindowAttributes m_pSetLayeredWindowAttributes;
//---------------------------------------------------------------------------

extern TCommThread * ptrTIUCommThread;				// pointer to TIU communications thread
extern bool TIUSelection[TIUMAX];                  // Flags to indicate that a TIU is present

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "_GClass"
#pragma link "AbCBitBt"
#pragma resource "*.dfm"
TWatchdog *Watchdog; 	// NOTE: this is public static variable, you can never use
						// this when you create multiple instances of a Form
//---------------------------------------------------------------------------
__fastcall TWatchdog::TWatchdog(TComponent* Owner)
    : TForm(Owner)
{
assert(false);	// never called since I used the overloaded constructor below
}
//---------------------------------------------------------------------------
__fastcall TWatchdog::TWatchdog(TComponent* Owner, int Remote, int TIU, int Engine)
    : TForm(Owner)
{
MyTIUNo = TIU;
assert(MyTIUNo >= 1 && MyTIUNo <= TIUMAX);
MyRemoteNo = Remote;
assert(MyRemoteNo >= 1 && MyRemoteNo <= REMOTEMAX);
MyEngineNo = Engine;
assert(MyEngineNo >= FACTORYRESET && MyEngineNo <= ENGINEMAX);
//
Caption = "Watchdog Signal for TIU #" + String(MyTIUNo);
WatchdogBitBtn1->Caption = "Send Watchdog TIU #" + String(MyTIUNo);;
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::WatchdogBitBtn1Click(TObject *Sender)
{
// Send Watchdog signal if we are connected to the TIU
if (MainForm->IsTIUConnected()) {
    const TCursor OldCursor = Screen->Cursor; 	// save cursor
    Screen->Cursor = crHourGlass;
    //WatchdogBitBtn1->Font->Color = clRed;
    WatchdogBitBtn1->Enabled = false;
    // I0 command generates a lot of DCS traffic on the track which simulates a Watchdog signal
    if (ptrTIUCommThread) {
        if (DEBUGGING) DB->Debug_Print("Watchdog Signal to TIU #" + String(MyTIUNo));
        #ifdef OLDWAY
        // next lines send an "I0" command (a Watchdog signal) to the given TIU and record the engines found as active.
        MainForm->Delay(WATCHDOGDELAY);
        MessageBeep(MB_ICONEXCLAMATION);
        MainForm->Delay(WATCHDOGWAIT);  // by experimentation, I found that a short delay works best
        MainForm->FindEngines(MyTIUNo);	// find engines on given TIU
        #else
        // next lines send an "I0" command (a Watchdog signal) to the given TIU
        // Start a Watchdog thread in interactive mode
            // Create suspended - in BCB 4.0, the thread constructor does not wait for lower level constructors itself.
            // The Execute() routine actually runs before some lower level construction is finished.
            // Don't put constructions in the thread constructor. if you have to, start the thread suspended and then start it running
            // per Remy LeBeau (TeamB) it is a known bug that was fixed in BCB 6.0
        Watchdog_Thread * ptrWatchdog_Thread = new Watchdog_Thread(true, MyRemoteNo, MyTIUNo, MyEngineNo, true);
        assert(ptrWatchdog_Thread);
        #if __BORLANDC__ >= 0x720
        ptrWatchdog_Thread->Start();			// start the thread for CB10.1
        #else
        ptrWatchdog_Thread->Resume();			// start the thread for BCB4.0 - use deprecated in CB10.1, use Start() instead
        #endif
        #endif
        }
    WatchdogBitBtn1->Enabled = true;
    //WatchdogBitBtn1->Font->Color = clWindowText;
    Screen->Cursor = OldCursor;
    }
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::FormActivate(TObject *Sender)
{
#if __BORLANDC__ >= 0x720      // CB10.1 only
AlphaBlend = false; // Remove Transparency
#else
// Remove WS_EX_LAYERED from this window styles
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) & ~WS_EX_LAYERED);
// Ask the window and its children to repaint
//Repaint();
#endif	    
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::FormDeactivate(TObject *Sender)
{
if (Setup->TransparentSpin->Value == Setup->TransparentSpin->MaxValue) return;	// Off
if (LocalTransparencyOverride) return;
#if __BORLANDC__ >= 0x720      // CB10.1 only
AlphaBlendValue = (255 * Setup->TransparentSpin->Value) / 100;
AlphaBlend = true;  // Add Transparency
#else
// Set WS_EX_LAYERED on this window
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
//SetLayeredWindowAttributes
m_pSetLayeredWindowAttributes(Handle, NULL, (255 * Setup->TransparentSpin->Value) / 100, LWA_ALPHA);
#endif    
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::NextTIUClick(TObject *Sender)
{
//
// send a message to MainForm to display the next TIU's Watchdog Button
// Active TIU numbers may not be sequential
int NewTIU = MyTIUNo;
// Find the next active TIU
for (int iCount = 1 ; iCount < TIUMAX ; iCount++) {
    if (NewTIU == TIUMAX) {
    	NewTIU = 1;
        } else {
        NewTIU += 1;
        }
    if (TIUSelection[NewTIU - 1]) {
        (void) PostMessage(MainForm->Handle, CM_SHOWWATCHDOG, NewTIU, MyEngineNo);
        break;
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::PrevTIUClick(TObject *Sender)
{
//
// send a message to MainForm to display the previous TIU's Watchdog Button
// Active TIU numbers may not be sequential
int NewTIU = MyTIUNo;
// Find the next active TIU
for (int iCount = 1 ; iCount < TIUMAX ; iCount++) {
    if (NewTIU == 1) {
        NewTIU = TIUMAX;
        } else {
        NewTIU -= 1;
        }
    if (TIUSelection[NewTIU - 1]) {
        (void) PostMessage(MainForm->Handle, CM_SHOWWATCHDOG, NewTIU, MyEngineNo);
        break;
        }
    }
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::CopyrightClick(TObject *Sender)
{
// Copy the Form to the clipboard.
// In BCB4.0, there is no SetSize method associated with TBitmap
// so we have to use Width and Height separately.
//
// see:
// https://stackoverflow.com/questions/3190777/how-do-i-copy-a-form-as-an-image-to-the-clipboard
//
Graphics::TBitmap * bm;
bm = new Graphics::TBitmap;
try
	{
    #if __BORLANDC__ >= 0x720
	// Defined for CB10.1 C++ programs that use the VCL.
	bm->SetSize(ClientWidth, ClientHeight);
    #else
    bm->Width = ClientWidth;
    bm->Height = ClientHeight;
    #endif
	BitBlt(bm->Canvas->Handle, 0, 0, ClientWidth, ClientHeight, Canvas->Handle, 0, 0, SRCCOPY);
    Clipboard()->Assign(bm);
    }
__finally
	{
	delete bm;
    }    
}
//---------------------------------------------------------------------------

void __fastcall TWatchdog::FormShow(TObject *Sender)
{
#if __BORLANDC__ >= 0x720
// Defined for CB10.1 C++ programs that use the VCL.
//
// See PC_Thread.cpp -- CallInputDropDown(void) for calling
// sequence for this code to correctly place the form when
// monitor 2 is requested.
// Call this form with this sequence
/*
#if __BORLANDC__ >= 0x720
// Defined for CB10.1 C++ programs that use the VCL.
DropDownQuery->Position    = poDesigned;
DropDownQuery->PopupMode = pmExplicit;
DropDownQuery->PopupParent = ptrPC;
#endif
retv = DropDownQuery->ShowModal();
*/
//
// Code developed with the help of Grok:
// https://grok.com/share/c2hhcmQtMg_7cadeded-7ad7-4353-88bd-ff9ae464b145
// https://grok.com/c/aac589ba-ab79-40aa-8e5a-82d400df210b?rid=954e999c-e1c3-4169-8faf-972a3e81e5c8
//
if (PopupParent)   // or pass the owner form another way
    {
        TForm* OwnerForm = dynamic_cast<TForm*>(PopupParent);

        if (OwnerForm)
        {
            HandleNeeded();

            Left = OwnerForm->Left + (OwnerForm->Width  - Width)  / 2;
            Top  = OwnerForm->Top  + (OwnerForm->Height - Height) / 2;
        }
    }

    MakeFullyVisible();   // Important for monitor 2
#endif     
}
//---------------------------------------------------------------------------

