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

© Copyright 2016 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/>.

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

#include "Message_Popup.h"
#include "Command_Query.h"
#include "Train_Control.h"
#include "Debug_Controls.h"
#include "PBFileThread.h"
#include "Hot_Com.h"
#include "Clipbrd.hpp"

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "AbNumEdit"
#pragma resource "*.dfm"

TCommand_Query_Form *Command_Query_Form;
//
// This form is autocreate
//
//---------------------------------------------------------------------------
__fastcall TCommand_Query_Form::TCommand_Query_Form(TComponent* Owner)
	: TForm(Owner)
{
if (DEBUGGING) ButtonEngNo->MinValue = 0;	// enable Engine 0
ButtonCommand->ItemIndex = 0;	// nothing selected at start - select first line in ButtonCommand
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::FormShow(TObject *Sender)
{
ButtonEngNoValueChanged(ButtonEngNo);
ButtonCommandChange(ButtonCommand);
if (ButtonEngNo->Value == LASHUPMIN) {
	LashUpCheckBox->Checked = true;
    EngPanel->Visible = true;
    }
#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
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::ButtonEngNoValueChanged(
      TObject *Sender)
{
// LashUp string entry possible only if Engine Number is == 101 (DCS #102)
if (ButtonEngNo->Value == LASHUPMIN) {
    //EngPanel->Visible = true;
    LashUpCheckBox->Checked = true;
    P3Panel->Visible = true;
    } else {
    //EngPanel->Visible = true;
    LashUpCheckBox->Checked = false;
    P3Panel->Visible = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::ButtonCommandChange(
      TObject *Sender)
{
// enable AIU and Port Number if this is an AIU command
if (ButtonCommand->ItemIndex <= 0) return;	// ignore if 0 (select first line in ButtonCommand)
String Cmd_Name = CommandListMemo->Lines->Strings[ButtonCommand->ItemIndex]; // need this to get the command letter
ButtonCommand->Hint = Cmd_Name;

P1->Visible = false;
P2->Visible = false;
P1->ReadOnly = false;
P2->ReadOnly = false;
P1Label->Visible = false;
P2Label->Visible = false;
EngPanel->Visible = true;
TIUPanel->Visible = true;
P3Panel->Visible = false;
P3Label->Caption = "LashUp String";
P3->Hint = "Enter Engines in LashUp separated by commas - Use minus sign for Reverse Running - eg: 3,-2,8";
BrowseButton->Visible = false;

if (Cmd_Name.IsEmpty() || Cmd_Name.SubString(1,2) == "//") {	// comment or blank line cannot be selected
	ButtonCommand->ItemIndex = 0;   // select first line in ButtonCommand
    return;
    }

if (ButtonEngNo->Value >= 101) {
    P3Panel->Visible = true;
    }

// Playback of Recorded File
if (Cmd_Name.Pos(TEXT("Playback of a Recorded File"))) {
    TIUPanel->Visible = false;
	EngPanel->Visible = false;
    P3Label->Caption = "Filename";
    BrowseButton->Visible = true;
    P3Panel->Visible = true;
    if (P3->Text.Pos(TEXT("."))) {
        // it's a file name
        P3->Hint = P3->Text;
    	} else {
	    P3->Hint = "Enter the playback filename or press Browse";
        }
    return;
	}
// set Speed
if (Cmd_Name.Pos(TEXT("=s%d"))) {
    P1->Visible = true;
    P1->MaxValue = SPEEDMAX; 	// use P1 (AIU) field for Speed
    P1->MinValue = 0;
    P1Label->Visible = true;
    P1Label->Caption = "Speed in Smph";
    P1->Hint = "Enter the Smph 0-120";
	}
// Activate a Route/Scene
if (Cmd_Name.Pos(TEXT("Activate a Route/Scene"))) {
    TIUPanel->Visible = false;
	EngPanel->Visible = false;
    P1->Visible = true;
    P1->MaxValue = 256;
    P1->MinValue = 1;
    P1Label->Visible = true;
    P1Label->Caption = "Route/Scene #";
    P1->Hint = "Select Route/Scene Number from 1 to 256";
	return;
    }
// AIU Commands - Normal AIU commands and special Watchdog Enabling Command
if (Cmd_Name.Pos(TEXT("=A")) || Cmd_Name.Pos(TEXT("Siding"))) {
	EngPanel->Visible = false;
    TIUPanel->Visible = true;
	P1->Visible = true;
    if (P1->Value > AIUMAX) P1->Value = 1;
    P1->MaxValue = AIUMAX;
    P1->MinValue = 1;
    P1Label->Visible = true;
    P1Label->Caption = "AIU Number";
    P1->Hint = "Select AIU Number from 1 to 5";
    if (Cmd_Name.Pos(TEXT("All "))) {
		P2Label->Visible = false;
    	P2->Visible = false;
        } else {
	    if (P2->Value > CHANMAX) P2->Value = 1;
	    P2->MaxValue = CHANMAX;
    	P2->MinValue = 1;
    	P2Label->Caption = "Port";
	    P2->Hint = "Select AIU Port Number from 1 to 10";
    	P2Label->Visible = true;
        P2->Visible = true;
        }
    return;
    }
// Emergency Stop
if (Cmd_Name.Pos(TEXT("=o0"))) {
	EngPanel->Visible = false;
    return;	// only uses TIU number
	}
// TIU DCS Control
if (Cmd_Name.Pos(TEXT("=O"))) {
	EngPanel->Visible = false;
    return;	// only uses TIU number
	}

// remaining commands need the Engine/LashUp Number

// Builtin Sounds or Custom Sounds
if (Cmd_Name.Pos(TEXT("=n%d")) || Cmd_Name.Pos(TEXT("=Sp%d"))) {
    P1->Visible = true;
    P1->MaxValue = 255; 	// use P1 (AIU) field for sound number
    P1->MinValue = 1;
    P1Label->Visible = true;
    P1Label->Caption = "Sound Number";
    P1->Hint = "Enter the sound number 1-255";
    return;
    }

// Volume Controls
if (Cmd_Name.Pos(TEXT("=v"))) {
    P1->Visible = true;
    P1->MaxValue = VOLMAX; 	// use P1 (AIU) field for Volume
    P1->MinValue = 0;
    P1Label->Visible = true;
    P1Label->Caption = "Volume Level";
    P1->Hint = "Enter the Volume Level 0-100";
    return;
    }

// Builtin Sounds
if (Cmd_Name.Pos(TEXT("=n"))) {	// nXXX in Cmd_Name
    P1->Visible = true;
    P1->MaxValue = 255; 	// use P1 (AIU) field for sound number
    P1->MinValue = 1;
    P1->ReadOnly = true;
    P1Label->Visible = true;
    P1Label->Caption = "Sound Number";
    P1->Hint = "Enter the sound number 1-255";
    // isolate out the sound number
    const int iPos =  Cmd_Name.Pos(TEXT("=n"));
	String MyCommand = Cmd_Name.SubString(iPos + 2, 25).Trim();
    P1->Value = MyCommand.ToIntDef(1); 	// set to 1 on error
    return;
    }
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::LashUpCheckBoxClick(TObject *Sender)
{
if (LashUpCheckBox->Checked == true) {
	ButtonEngNo->Value = LASHUPMIN;
    P3Panel->Visible = true;
    } else {
	ButtonEngNo->Value = ENGINEMIN;
    P3Panel->Visible = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::ClearButtonClick(TObject *Sender)
{
// Clear the fields
ButtonName->Text = "Button" + String(ButtonNo);
ButtonCommand->ItemIndex = 0;   // select first line in ButtonCommand
ButtonTIUNo->Value = 1;
ButtonEngNo->Value = 1;
LashUpCheckBox->Checked = false;
//
P1->Value = 1;
P2->Value = 1;
//
P3->Text = "";
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::BrowseButtonClick(TObject *Sender)
{
// browse for playback filename
PBDialog->InitialDir = MainForm->WorkingDir;
PBDialog->DefaultExt = String("rtc");
PBDialog->Title = "Select a Playback File";
PBDialog->Filter = "Remote Train Control files (*.rtc)|*.rtc";
PBDialog->FileName = "*.rtc";
PBDialog->Options = PBDialog->Options << ofEnableSizing << ofPathMustExist << ofFileMustExist;
										 // Allow Resizing
PBDialog->FileName = P3->Text;

if (PBDialog->Execute()) {
	P3->Text = PBDialog->FileName;
   	// Change working directory to whatever was selected
   	MainForm->WorkingDir = ExtractFilePath(PBDialog->FileName);
   	if (DEBUGGING) DB->Debug_Print("Edit Hot Button (Playback): " + PBDialog->FileName);
	}
P3->Hint = PBDialog->FileName;
return;	// user canceled the File Open Dialog
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::OKButtonClick(TObject *Sender)
{
ModalResult = mrOk;
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::CancelButtonClick(TObject *Sender)
{
ModalResult = mrCancel;
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::FormKeyDown(TObject *Sender,
      WORD &Key, TShiftState Shift)
{
// Make sure KeyPreview is true for this form
assert(KeyPreview);
// Pass function keys to the MainForm, handle rest of the keys here.
switch (Key) {
    case VK_F1:
    case VK_F2:
    case VK_F3:
    case VK_F4:
    case VK_F5:
    case VK_F6:
    case VK_F7:
    case VK_F8:
    case VK_F9:
    case VK_F10:
    case VK_F11:
    case VK_F12:
		MainForm->FormKeyDown(Sender, Key, Shift);
        Key = 0;	// handled
		break;
	}	
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::PBDialogShow(TObject *Sender)
{
// change Open button to "Select"
// http://www.bcbjournal.org/articles/vol3/9912/Changing_common_dialog_button_captions.htm
HWND hWndDlg = GetParent(PBDialog->Handle);
if (hWndDlg == NULL) {
	if (DEBUGGING) DB->Debug_Print("GetParent() returned NULL");
    LPVOID lpMsgBuf;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL);

    // Display the string.
	if (DEBUGGING) DB->Debug_Print(String((char *)lpMsgBuf));
    // Free the buffer.
    LocalFree( lpMsgBuf );
	} else {
	HWND hWndBtn = GetDlgItem(hWndDlg, IDOK); //1);
	if (hWndBtn == NULL) {
		if (DEBUGGING) DB->Debug_Print("Control does not exist");
		} else {
		SetWindowText(hWndBtn, TEXT("Select"));
    	}
    }
}
//---------------------------------------------------------------------------

void __fastcall TCommand_Query_Form::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;
    }    
}
//---------------------------------------------------------------------------

