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

© Copyright 2015 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 "DCS_Setup_Controls.h"
#include "Train_Control.h"
#include <stdio.h>
#include "Conv_Mode.h"
#include "Comm_Thread.h"
#include "Clipbrd.hpp"


//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "_GClass"
#pragma link "AbSwitch"
#pragma link "AbCBitBt"
#pragma resource "*.dfm"
//---------------------------------------------------------------------------
//TDCS_Setup *DCS_Setup;	// NOTE: this is public static variable, you can never use
			// this when you create multiple instances of a Form
            // In this case, there can be 10 instances of this Form, one for each TIU and Channel
//---------------------------------------------------------------------------
extern TConvMode * ptrConvMode[TIUMAX][CONVMAX];		// Conventional Mode Pointers, 5 TIU, 2 channels - indexed by TIUNo-1 and ChannelNo-1

extern TCommThread * ptrTIUCommThread;				// pointer to TIU communications thread
//---------------------------------------------------------------------------
__fastcall TDCS_Setup::TDCS_Setup(TComponent* Owner)
	: TForm(Owner)
{
assert(false); 	// never called since I used the overloaded constructor below
}
//---------------------------------------------------------------------------
__fastcall TDCS_Setup::TDCS_Setup(TComponent* Owner, int Remote, int Engine, int TIU)
	: TForm(Owner)
{
TIUNo = TIU;
RemoteNo = Remote;
EngineNo = Engine;
ChannelNo = 0;
Signal_Controls_Label->Caption = "Signal Setup for TIU " + String(TIUNo);
this->Caption = Signal_Controls_Label->Caption;

// read preferences from the Registry
RegFileRootKey = MainForm->RegFileRootKey;
// read Preferences from registry if they exist
TRegIniFile * const RegFile = new TRegIniFile(RegFileRootKey);
assert(RegFile != NULL);
__try {
    // DCS Setup loaded on a per TIU basis
	MainForm->SetSwitch(Var1Signal, RegFile->ReadInteger("TIU", "Var1Signal" + String(TIUNo), Var1Signal->Checked & 0x01));
	MainForm->SetSwitch(Var2Signal, RegFile->ReadInteger("TIU", "Var2Signal" + String(TIUNo), Var2Signal->Checked & 0x01));
	MainForm->SetSwitch(Fixed1Signal, RegFile->ReadInteger("TIU", "Fixed1Signal" + String(TIUNo), Fixed1Signal->Checked & 0x01));
	MainForm->SetSwitch(Fixed2Signal, RegFile->ReadInteger("TIU", "Fixed2Signal" + String(TIUNo), Fixed2Signal->Checked & 0x01));
	MainForm->SetSwitch(Var1ModeSwitch, RegFile->ReadInteger("TIU", "Var1ModeSwitch" + String(TIUNo), Var1ModeSwitch->Checked & 0x01));
   	MainForm->SetSwitch(Var2ModeSwitch, RegFile->ReadInteger("TIU", "Var2ModeSwitch" + String(TIUNo), Var2ModeSwitch->Checked & 0x01));
    }
__finally {
	// Deallocate RegFile
	delete RegFile;
    }
}
//---------------------------------------------------------------------------
__fastcall TDCS_Setup::~TDCS_Setup(void)
{
// write preferences to the Registry - Note: MainForm->RegFileRootKey was destroyed by the time this ran
// so I had to save the value locally
if (MainForm->bSaveRegistryInfo) {
	TRegIniFile * const RegFile = new TRegIniFile(RegFileRootKey);
	assert(RegFile != NULL);
	__try {
		// DCS Setup saved on a per TIU basis
		RegFile->WriteInteger("TIU", "Var1Signal" + String(TIUNo), Var1Signal->Checked);
		RegFile->WriteInteger("TIU", "Var2Signal" + String(TIUNo), Var2Signal->Checked);
		RegFile->WriteInteger("TIU", "Fixed1Signal" + String(TIUNo), Fixed1Signal->Checked);
		RegFile->WriteInteger("TIU", "Fixed2Signal" + String(TIUNo), Fixed2Signal->Checked);
		RegFile->WriteInteger("TIU", "Var1ModeSwitch" + String(TIUNo), Var1ModeSwitch->Checked);
		RegFile->WriteInteger("TIU", "Var2ModeSwitch" + String(TIUNo), Var2ModeSwitch->Checked);
		}
	__finally {
		// Deallocate RegFile
		delete RegFile;
		}
	}
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Var1ModeSwitchStatusChanged(TObject *Sender)
{
// FXD Mode Switch - Var 1
if (Var1ModeSwitch->Checked) {
	// Fixed Mode on
	(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Ob00", TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
    if (ptrConvMode[TIUNo - 1][0]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][0]->VarXModeSwitch->Checked = true;
    	}
    } else {
    // Variable Mode on
	(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Ob01", TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
    if (ptrConvMode[TIUNo - 1][0]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][0]->VarXModeSwitch->Checked = false;
    	}
    }
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Var2ModeSwitchStatusChanged(TObject *Sender)
{
// FXD Mode Switch - Var 2
if (Var2ModeSwitch->Checked) {
	// Fixed Mode on
	(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Ob10", TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
    if (ptrConvMode[TIUNo - 1][1]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][1]->VarXModeSwitch->Checked = true;
    	}
    } else {
    // Variable Mode on
	(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Ob11", TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
    if (ptrConvMode[TIUNo - 1][1]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][1]->VarXModeSwitch->Checked = false;
    	}
    }
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::AllSignalOnClick(TObject *Sender)
{
// All on
Var1Signal->Checked = true;
Fixed1Signal->Checked = true;
Fixed2Signal->Checked = true;
Var2Signal->Checked = true;
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Oa1111", TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::AllSignalOffClick(TObject *Sender)
{
// All off
Var1Signal->Checked = false;
Fixed1Signal->Checked = false;
Fixed2Signal->Checked = false;
Var2Signal->Checked = false;
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, "Oa0000", TIUNo, RemoteNo, 11, LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::HideButtonClick(TObject *Sender)
{
Hide();	      // Same as setting Visible to false		
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Var1SignalStatusChanged(TObject *Sender)
{
ChannelNo = 0;  // TIU channel 0-3 (Var1 = 0, Fixed1 = 1, Fixed2 = 2, Var2 = 3)
char str[15];

if (Var1Signal->Checked) {
	// DCS signal on
	(void)snprintf(str, sizeof str, "Od%d1", ChannelNo);
	} else {
	// DCS signal off
	(void)snprintf(str, sizeof str, "Od%d0", ChannelNo);
    }
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, str, TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
//
if (Var1Signal->Checked) {
    // DCS signal on
    if (ptrConvMode[TIUNo - 1][0]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][0]->VarXSignal->Checked = true;
    	}
    } else {
    // DCS signal off
    if (ptrConvMode[TIUNo - 1][0]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][0]->VarXSignal->Checked = false;
    	}
    }
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Fixed1SignalStatusChanged(TObject *Sender)
{
ChannelNo = 1;  // TIU channel 0-3 (Var1 = 0, Fixed1 = 1, Fixed2 = 2, Var2 = 3)
char str[15];

if (Fixed1Signal->Checked) {
	// DCS signal on
	(void)snprintf(str, sizeof str, "Od%d1", ChannelNo);
	} else {
	// DCS signal off
	(void)snprintf(str, sizeof str, "Od%d0", ChannelNo);
    }
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, str, TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Fixed2SignalStatusChanged(TObject *Sender)
{
ChannelNo = 2;  // TIU channel 0-3 (Var1 = 0, Fixed1 = 1, Fixed2 = 2, Var2 = 3)
char str[15];

if (Fixed2Signal->Checked) {
	// DCS signal on
	(void)snprintf(str, sizeof str, "Od%d1", ChannelNo);
	} else {
	// DCS signal off
	(void)snprintf(str, sizeof str, "Od%d0", ChannelNo);
    }
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, str, TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
}
//---------------------------------------------------------------------------

void __fastcall TDCS_Setup::Var2SignalStatusChanged(TObject *Sender)
{
ChannelNo = 3;  // TIU channel 0-3 (Var1 = 0, Fixed1 = 1, Fixed2 = 2, Var2 = 3)
char str[15];

if (Var2Signal->Checked) {
	// DCS signal on
	(void)snprintf(str, sizeof str, "Od%d1", ChannelNo);
	} else {
	// DCS signal off
	(void)snprintf(str, sizeof str, "Od%d0", ChannelNo);
    }
(void)ptrTIUCommThread->Send_String_FIFO(EngineNo, str, TIUNo, RemoteNo, 11, VERY_LONG_WAIT, RECORD_OK, NULL, NULL, NULL);
//
if (Var2Signal->Checked) {
    // DCS signal on
    if (ptrConvMode[TIUNo - 1][1]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][1]->VarXSignal->Checked = true;
    	}
    } else {
    // DCS signal off
    if (ptrConvMode[TIUNo - 1][1]) {	// reflect the change on to any open Conventional Mode window
        ptrConvMode[TIUNo - 1][1]->VarXSignal->Checked = false;
    	}
    }
}
//---------------------------------------------------------------------------


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



