//===========================================================================//
// File:	thermalsight.hpp                                                    //
// Project: BattleTech                                                       //
// Contents: ThermalSight (thermal / infra-red vision mode) subsystem        //
//---------------------------------------------------------------------------//
// Copyright (C) 1995, Virtual World Entertainment, Inc. All Rights reserved //
//                      PROPRIETARY AND CONFIDENTIAL                         //
//===========================================================================//
//
// RECONSTRUCTED from the shipped binary (Ghidra pseudo-C, recovered shard
// part_013.c).  NO THERMALSIGHT.HPP survived; the class body is inferred from
// usage and the embedded string pool.  Each method cites its @ADDR.
//
// IDENTIFICATION:
//   * mech3.cpp factory map: ThermalSight::CreateStreamedSubsystem @004b87d4,
//     DefaultData &DAT_00511228.
//   * vtable @00511498 (slot0 dtor @004b8794), ctor @004b8718.
//   * CreateStreamedSubsystem @004b87d4 stamps classID 0x0BDE and streamed
//     model size 0xF4; it parses NO thermal-specific model fields.
//   * String pool @00511474 ("ThermalSight", "LightOn", "LightState").
//     ClassDerivations name "ThermalSight" @00511238.
//   * Its per-frame update toggles the GLOBAL "pvision" (pixel/thermal vision)
//     render flag via FUN_0045fe44 (which prints "pvision ON"/"pvision OFF",
//     strings @004f2f9d/@004f2fa8) -- confirming this is the cockpit IR/thermal
//     view-mode subsystem rather than a world light.
//
// BASE CLASS:
//   ThermalSight IS-A PowerWatcher (powersub.hpp): ctor @004b8718 chains to the
//   PowerWatcher ctor FUN_004b18a4 with &DAT_00511228, and
//   CreateStreamedSubsystem chains to PowerWatcher::CreateStreamedSubsystem
//   FUN_004b198c.  Shared base 0..0x1D8; own members begin at 0x1D8.  Exposes
//   one queryable attribute "LightState".  Unlike Searchlight it does NOT
//   override the network-replication slots (6/7) -- it inherits the base.
//
#if !defined(THERMALSIGHT_HPP)
#	define THERMALSIGHT_HPP

#if !defined(POWERSUB_HPP)
	#include "powersub.hpp"
#endif

//##########################################################################
//#####################    Local multi-level alarm shim    #################
//##########################################################################
//
// CROSS-FAMILY: heat.hpp does `typedef GaugeAlarm AlarmIndicator;` but the
// engine GaugeAlarm (GAUGALRM.h) has a PROTECTED ctor/dtor and no
// Initialize/Finalize/SetLevel; the mech.hpp/mechrecon.hpp alias resolves
// AlarmIndicator to ReconAlarm, which also lacks Initialize/Finalize.  Until
// the heat family provides a real multi-level AlarmIndicator, this module owns
// a tiny faithful stand-in for ITS OWN alarm member (it does NOT redefine the
// AlarmIndicator typedef).
//
#if !defined(BT_LOCAL_ALARM_SHIM)
#	define BT_LOCAL_ALARM_SHIM
	struct BtAlarm
	{
		int		level;
		BtAlarm()					: level(0) {}
		void	Initialize(int /*levels*/)	{ level = 0; }	// FUN_0041b9ec
		void	Finalize()					{}				// FUN_0041baa4
		void	SetLevel(int n)				{ level = n; }	// FUN_0041bbd8
		int		GetLevel() const			{ return level; }
	};
#endif

//##########################################################################
//####################    ThermalSight::SubsystemResource    ###############
//##########################################################################
//
// Empty extension of the PowerWatcher resource (CreateStreamedSubsystem
// @004b87d4 reads no thermal-specific fields).
//
	struct ThermalSight__SubsystemResource:
		public PowerWatcher::SubsystemResource
	{
	};

//##########################################################################
//#########################    ThermalSight    #############################
//##########################################################################

	class ThermalSight:
		public PowerWatcher
	{
		friend struct ThermalSightLayoutCheck;	// compile-time offset locks (thermalsight.cpp)
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data Support
	//
	// DefaultData @00511228, ClassDerivations @00511238 ("ThermalSight").
	//
	public:
		static Derivation ClassDerivations;		// @00511238
		static SharedData DefaultData;			// @00511228
		static Receiver::MessageHandlerSet MessageHandlers;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Attribute Support
	//
	// AttributePointers IndexEntry table @00511270:
	//      id 4  "LightState"  -> @0x1D8   (offset encoded 0x1D9 == 0x1D8|1)
	//
	public:
		enum {
			LightStateAttributeID = PowerWatcher::NextAttributeID,	// 4
			NextAttributeID
		};

	private:
		static const IndexEntry AttributePointers[];	// @00511270
	protected:
		static AttributeIndexSet AttributeIndex;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Local data.
	//
	protected:
		int		thermalActive;	// @0x1D8  reported IR mode on/off (gated by power + heat); "LightState"
		int		requestedOn;	// @0x1DC  init 0; on/off input consumed by ThermalSightSimulation
		BtAlarm	stateAlarm;		// @0x1E0  2-level indicator (size 0x54)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// BT segment / base-state compatibility shims (CROSS-FAMILY).
	//
	// Logically belong on the shared bases (Subsystem::GetSegmentFlags,
	// PowerWatcher::HostShutDown / WatchedVoltageLevel, HeatSink::HeatStateLevel)
	// plus the cockpit view-mode hooks (the locally-viewed-mech viewport and the
	// global "pvision" thermal toggle, FUN_0045fe44).  Backed locally so this
	// module compiles; see report.
	//
	public:
		// De-shimmed (WAVE 4 un-stub): the 5 CROSS-FAMILY backing fields
		// (segmentFlags/hostShutDown/watchedVoltageLevel/heatStateLevel/
		// localViewport) + struct BtViewport are DELETED.  They duplicated
		// engine-base state AND -- via the old shadow `segmentFlags` (seeded 0) --
		// made the ctor gate ((0&0xC)==0 && (0&0x100)!=0) FALSE, so
		// ThermalSightSimulation was NEVER installed.  Accessors now read the REAL
		// inherited base members (mirrors torso.hpp / searchlight.hpp):
		//   HostShutDown        <- MechSubsystem::simulationState == Destroyed (this+0x40)
		//   WatchedVoltageLevel <- PowerWatcher::watchdogAlarm level           (this+0x198)
		//   HeatStateLevel      <- HeatWatcher::heatAlarm level                (this+0x140)
		// The cockpit IR view-mode RENDER hooks have no ported target and stay
		// clearly-marked no-ops for bring-up (thermalActive/stateAlarm are still
		// computed faithfully):
		//   IsLocallyViewed()  -- was localViewport->viewingThisMech (L4 viewport
		//                         global PTR_DAT_004fd4b8+0x48); no ported accessor.
		//   ToggleGlobalThermalVision() -- was FUN_0045fe44 (global "pvision"
		//                         palette flip); the D3D9 renderer has no pvision.
		Logical		HostShutDown() const		{ return simulationState == 1; /* Destroyed */ }
		int			WatchedVoltageLevel() const	{ return watchdogAlarm.GetLevel(); }	// @0x198
		int			HeatStateLevel() const		{ return heatAlarm.GetLevel(); }		// @0x140
		Logical		IsLocallyViewed() const		{ return False; }	// bring-up no-op (see above)
		void		ToggleGlobalThermalVision()	{}					// bring-up no-op (pvision unported)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Simulation Support
	//
	public:
		typedef void
			(ThermalSight::*Performance)(Scalar time_slice);

		void
			SetPerformance(Performance performance)
			{
				Check(this);
				activePerformance = (Simulation::Performance)performance;
			}

		void
			ThermalSightSimulation(Scalar time_slice);	// @004b8648 (Performance, PTR @00511290)

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Class Support
	//
	public:
		static	Logical	TestClass(Mech&);
		Logical			TestInstance() const;	// @004b881c

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Construction and Destruction
	//
	// vtable @00511498 differs from the PowerWatcher base only in slot0 (dtor)
	// and the inherited PowerWatcher slots 9/10 (@004b179c / @004b1804); no
	// further virtual overrides.
	//
	public:
		typedef ThermalSight__SubsystemResource SubsystemResource;

		ThermalSight(
			Mech				*owner,
			int					subsystem_ID,
			SubsystemResource	*subsystem_resource,
			SharedData			&shared_data = DefaultData
		);											// @004b8718
		~ThermalSight();							// @004b8794

		static int
			CreateStreamedSubsystem(				// @004b87d4
				NotationFile				*model_file,
				const char					*model_name,
				const char					*subsystem_name,
				SubsystemResource			*subsystem_resource,
				NotationFile				*subsystem_file,
				const ResourceDirectories	*directories,
				int							passes = 1
			);
	};

#endif
