//---------------------------------------------------------------------------
/*
Remote Train Control Program for Windows

© Copyright 2019 by Mark DiVecchio

    This file is part of Remote Train Control.

    Remote Train Control is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Remote Train Control is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Remote Train Control.  If not, see <http://www.gnu.org/licenses/>.

*/
//---------------------------------------------------------------------------
/*
This thread displays a message for certain time in a popup window, the
status bar and (if the Debug Window is opened) in the Debug Window.
*/
//---------------------------------------------------------------------------
#include <vcl.h>
#include <tchar.h>
#pragma hdrstop

#include "Message_Thread.h"
#include "Train_Control.h"
#include "Debug_Controls.h"
#include "Comm_Thread.h"

#pragma package(smart_init)

extern TCommThread * ptrTIUCommThread;				// pointer to TIU communications thread

//---------------------------------------------------------------------------
//   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 MessageDisplayThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------
__fastcall TMessageDisplayThread::TMessageDisplayThread(bool CreateSuspended)
	: TThread(CreateSuspended)
{
assert(false);	// never called since I used the overloaded constructor below
}
//---------------------------------------------------------------------------
__fastcall TMessageDisplayThread::TMessageDisplayThread(bool CreateSuspended, TForm * Callingthis, HWND Parent,
	String Caption, String MessageLine, String StatusLine, int dly)
	: TThread(CreateSuspended)
{
// Called in the context of the main VCL thread so VCL calls are ok
assert (dly >= 1 && dly <= 10000);
// post message for "dly" milliseconds
// grab the Parent's Handle
ParentHandle = Parent;
// Calling window
CallingScreen = Callingthis;

Msg_Caption = Caption;
if (Msg_Caption.IsEmpty()) Msg_Caption = "Information";

Msg_MessageLine = MessageLine;
if (Msg_MessageLine.IsEmpty()) Msg_MessageLine = "No Message";

Msg_StatusLine = StatusLine;
if (Msg_StatusLine.IsEmpty()) Msg_StatusLine = "--";

// Milliseconds to Display the Message
Msg_Delay = dly;

MyMessagePopup = NULL;

Finished = false;
// FreeOnTerminate is set so that parent does not have to worry about it
FreeOnTerminate = true;
// termination
OnTerminate = &RunOnTerminate;
}
//---------------------------------------------------------------------------
__fastcall TMessageDisplayThread::~TMessageDisplayThread()
{
if (MyMessagePopup != NULL) {
    MyMessagePopup->Hide();
    delete MyMessagePopup ;
    }
Finished = true;
}
//---------------------------------------------------------------------------

void __fastcall TMessageDisplayThread::Execute()
{
// Calls to Sleep() are ok in this thread
// NO VCL Calls in this thread

if (DEBUGGINGX(8)) {
	// print the ThreadId
    ptrTIUCommThread->PrintItem("TMessageDisplayThread: ThreadID " + IntToHex((int)GetCurrentThreadId(), 8), (TColor) clGreen);
    }

// this does not seem to work in BCB4.0 and Thread view not available in CB10.1
// it does work on BCB6.0
// http://docwiki.embarcadero.com/RADStudio/Rio/en/Converting_an_Unnamed_Thread_to_a_Named_Thread
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = "Message_Thread";
info.dwThreadID = -1;
info.dwFlags = 0;
__try {
    RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
        (DWORD*)&info);
    }
__except (EXCEPTION_CONTINUE_EXECUTION) {
    }

if (Terminated) {
	return;					// in case we are terminated
    }
//
Synchronize(Msg_Up);		// Display the message synchronously
Sleep(Msg_Delay);           // Calls to Sleep() are ok in this thread
//
// in BCB 4.0, the Synchronize call is not executed and the message box
// stays on the screen.
//
// in CB 10.1, the message box is correctly taken down
//
if (!Terminated)
    Synchronize(Msg_Dn);	// Take down the message display synchronously
}
//---------------------------------------------------------------------------

void __fastcall TMessageDisplayThread::Msg_Up(void)     // called using Synchronize()
{
//
if (DEBUGGING) {
    if (Msg_Caption == "Error") DB->Debug_Messages->SelAttributes->Color = clRed;
    if (!Msg_StatusLine.IsEmpty()) {
        DB->Debug_Print(Msg_Caption + " - " + Msg_MessageLine + " - " + Msg_StatusLine);
        } else {
        DB->Debug_Print(Msg_Caption + " - " + Msg_MessageLine);
        }
    }
//
if (!MyMessagePopup) {
	MyMessagePopup = new TMessagePopup(CallingScreen, ParentHandle, NULL, NULL);     // Synchronize() Pass "this" as the owner
	assert(MyMessagePopup != NULL);		// make sure that construction worked
   	}
MyMessagePopup->Show();
if (!Msg_StatusLine.IsEmpty())  MyMessagePopup->StatusLine->Caption = Msg_StatusLine;
if (!Msg_Caption.IsEmpty())     MyMessagePopup->Caption = Msg_Caption;
if (!Msg_MessageLine.IsEmpty()) MyMessagePopup->MessageLine->Caption = Msg_MessageLine;
MyMessagePopup->Repaint();
}
//---------------------------------------------------------------------------

void __fastcall TMessageDisplayThread::Msg_Dn(void)     // called using Synchronize()
{
if (MyMessagePopup != NULL) {
    MyMessagePopup->Hide();
    delete MyMessagePopup;
    }
MyMessagePopup = NULL;
}
//---------------------------------------------------------------------------

void __fastcall TMessageDisplayThread::RunOnTerminate(TObject * Sender)     // called Automatically using Synchronize()
{
if (MyMessagePopup != NULL) {
    MyMessagePopup->Hide();
    delete MyMessagePopup ;
    }
MyMessagePopup = NULL;
}
//---------------------------------------------------------------------------

