#include <wx/mstream.h>
#include <wx/artprov.h>
#include "../Headers/ResourceManager.h"

#include "../Headers/Resources/BMP180_ImageData.h"
#include "../Headers/Resources/BMP280_ImageData.h"
#include "../Headers/Resources/DHT11_ImageData.h"
#include "../Headers/Resources/DualLED_ImageData.h"
#include "../Headers/Resources/HCSR501_ImageData.h"
#include "../Headers/Resources/LCD1602_ImageData.h"
#include "../Headers/Resources/LED_ImageData.h"
#include "../Headers/Resources/MCP3008_ImageData.h"
#include "../Headers/Resources/Motor_ImageData.h"
#include "../Headers/Resources/MQ2_ImageData.h"
#include "../Headers/Resources/MQ3_ImageData.h"
#include "../Headers/Resources/MQ4_ImageData.h"
#include "../Headers/Resources/MQ5_ImageData.h"
#include "../Headers/Resources/MQ6_ImageData.h"
#include "../Headers/Resources/MQ7_ImageData.h"
#include "../Headers/Resources/MQ8_ImageData.h"
#include "../Headers/Resources/MQ9_ImageData.h"
#include "../Headers/Resources/MQ135_ImageData.h"
#include "../Headers/Resources/PCF8591_ImageData.h"
#include "../Headers/Resources/Photoresistor_ImageData.h"
#include "../Headers/Resources/PiCamera_ImageData.h"
#include "../Headers/Resources/PMS5003_ImageData.h"
#include "../Headers/Resources/PTQS1005_ImageData.h"
#include "../Headers/Resources/QSFS01_ImageData.h"
#include "../Headers/Resources/RainSensor_ImageData.h"
#include "../Headers/Resources/Receiver_ImageData.h"
#include "../Headers/Resources/Relay_ImageData.h"
#include "../Headers/Resources/RGBLED_ImageData.h"
#include "../Headers/Resources/RotaryEncoder_ImageData.h"
#include "../Headers/Resources/SoundSensor_ImageData.h"
#include "../Headers/Resources/TSL2591_ImageData.h"
#include "../Headers/Resources/Vehicle_ImageData.h"

//Main-thread only: this lazy image cache is an unsynchronized std::map. Both callers (GetComponentImage via the
//ComponentData ctor, GetAlertLevelImage via the logger model) run on the UI thread; building a tile/icon off the
//worker thread would race this map. Add a mutex here if that ever changes.
std::map<RumPi::EComponentType, wxImage> ResourceManager::myComponentImageMap;

/**
* Gets the icon for a component type, decoding it from its embedded PNG data on first request and caching it for
* subsequent calls.
*
* @author Eddie O'Hagan
* @date 8/13/2026
*
* @code
*	wxImage icon = ResourceManager::GetComponentImage(RumPi::EComponentType::E_LED);
* @endcode
*
* @param [in] theImageType The component type whose icon to get.
*
* @return The component's icon, or an empty wxImage if the PNG failed to decode.
*/
wxImage ResourceManager::GetComponentImage(RumPi::EComponentType theImageType)
{
	unsigned char* imageDataToLoad;
	unsigned int lengthOfImageDataToLoad;

	//Check if the corresponding image is loaded. if it's not, then load it.
	if (myComponentImageMap[theImageType].IsOk() == false)
	{
		if (theImageType == RumPi::EComponentType::E_BMP180)
		{
			imageDataToLoad = BMP180_png;
			lengthOfImageDataToLoad = BMP180_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_BMP280)
		{
			imageDataToLoad = BMP280_png;
			lengthOfImageDataToLoad = BMP280_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_DHT11)
		{
			imageDataToLoad = DHT11_png;
			lengthOfImageDataToLoad = DHT11_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_DualLED)
		{
			imageDataToLoad = DualLED_png;
			lengthOfImageDataToLoad = DualLED_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_HCSR501)
		{
			imageDataToLoad = HCSR501_png;
			lengthOfImageDataToLoad = HCSR501_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_LCD1602)
		{
			imageDataToLoad = LCD1602_png;
			lengthOfImageDataToLoad = LCD1602_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_LED)
		{
			imageDataToLoad = LED_png;
			lengthOfImageDataToLoad = LED_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MCP3008)
		{
			imageDataToLoad = MCP3008_png;
			lengthOfImageDataToLoad = MCP3008_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_Motor)
		{
			imageDataToLoad = Motor_png;
			lengthOfImageDataToLoad = Motor_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ2)
		{
			imageDataToLoad = MQ2_png;
			lengthOfImageDataToLoad = MQ2_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ3)
		{
			imageDataToLoad = MQ3_png;
			lengthOfImageDataToLoad = MQ3_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ4)
		{
			imageDataToLoad = MQ4_png;
			lengthOfImageDataToLoad = MQ4_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ5)
		{
			imageDataToLoad = MQ5_png;
			lengthOfImageDataToLoad = MQ5_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ6)
		{
			imageDataToLoad = MQ6_png;
			lengthOfImageDataToLoad = MQ6_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ7)
		{
			imageDataToLoad = MQ7_png;
			lengthOfImageDataToLoad = MQ7_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ8)
		{
			imageDataToLoad = MQ8_png;
			lengthOfImageDataToLoad = MQ8_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ9)
		{
			imageDataToLoad = MQ9_png;
			lengthOfImageDataToLoad = MQ9_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_MQ135)
		{
			imageDataToLoad = MQ135_png;
			lengthOfImageDataToLoad = MQ135_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_PCF8591)
		{
			imageDataToLoad = PCF8591_png;
			lengthOfImageDataToLoad = PCF8591_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_Photoresistor)
		{
			imageDataToLoad = Photoresistor_png;
			lengthOfImageDataToLoad = Photoresistor_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_PiCamera)
		{
			imageDataToLoad = PiCamera_png;
			lengthOfImageDataToLoad = PiCamera_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_PMS5003)
		{
			imageDataToLoad = PMS5003_png;
			lengthOfImageDataToLoad = PMS5003_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_PTQS1005)
		{
			imageDataToLoad = PTQS1005_png;
			lengthOfImageDataToLoad = PTQS1005_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_QSFS01)
		{
			imageDataToLoad = QSFS01_png;
			lengthOfImageDataToLoad = QSFS01_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_RainSensor)
		{
			imageDataToLoad = RainSensor_png;
			lengthOfImageDataToLoad = RainSensor_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_Receiver)
		{
			imageDataToLoad = Receiver_png;
			lengthOfImageDataToLoad = Receiver_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_Relay)
		{
			imageDataToLoad = Relay_png;
			lengthOfImageDataToLoad = Relay_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_RGBLED)
		{
			imageDataToLoad = RGBLED_png;
			lengthOfImageDataToLoad = RGBLED_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_RotaryEncoder)
		{
			imageDataToLoad = RotaryEncoder_png;
			lengthOfImageDataToLoad = RotaryEncoder_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_SoundSensor)
		{
			imageDataToLoad = SoundSensor_png;
			lengthOfImageDataToLoad = SoundSensor_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_TSL2591)
		{
			imageDataToLoad = TSL2591_png;
			lengthOfImageDataToLoad = TSL2591_png_len;
		}
		else if (theImageType == RumPi::EComponentType::E_Vehicle)
		{
			imageDataToLoad = Vehicle_png;
			lengthOfImageDataToLoad = Vehicle_png_len;
		}
		else
		{
			//Unmapped type (e.g. E_Unknown, or a component with no icon such as SystemHealthComponent): return an
			//empty image rather than silently showing the Vehicle icon.
			return wxImage();
		}

		//Attempt to load the image using a memory input stream.
		wxMemoryInputStream imageStream(imageDataToLoad, lengthOfImageDataToLoad);
		if (myComponentImageMap[theImageType].LoadFile(imageStream, wxBITMAP_TYPE_PNG) == false)
		{
			//Failed to load.
			return wxImage();
		}
	}

	return myComponentImageMap[theImageType];
}

/**
* Gets the alert-level glyph (tick / warning / error) from the platform's art provider, sized for a list control.
*
* @author Eddie O'Hagan
* @date 8/13/2026
*
* @code
*	wxBitmapBundle glyph = ResourceManager::GetAlertLevelImage(RumPi::EAlertLevel::Warning);
* @endcode
*
* @param [in] alertLevel The alert level whose glyph to get.
*
* @return The glyph for the alert level.
*/
wxBitmapBundle ResourceManager::GetAlertLevelImage(const RumPi::EAlertLevel& alertLevel)
{
	//Size the glyph to whatever the platform recommends for a list/report control.
	const wxSize size = wxArtProvider::GetSizeHint(wxART_LIST);

	if (alertLevel == RumPi::EAlertLevel::OK)
	{
		return wxArtProvider::GetBitmapBundle(wxART_TICK_MARK, wxART_LIST, size);
	}
	else if (alertLevel == RumPi::EAlertLevel::Warning)
	{
		return wxArtProvider::GetBitmapBundle(wxART_WARNING, wxART_LIST, size);
	}
	else //if (alertLevel == RumPi::EAlertLevel::Alert)
	{
		return wxArtProvider::GetBitmapBundle(wxART_ERROR, wxART_LIST, size);
	}
}