#include "SkyPortalRunner.h"
#include "SkyPortalFigure.h"
#include "SkyPortalSubsystem.h"

FPortalStatusChecker::FPortalStatusChecker(UEngineSubsystem* InSubsystem, float InCheckInterval)
	: SkyPortalSubsystemRef(InSubsystem), CheckInterval(InCheckInterval), bShouldRun(true)
{
}

bool FPortalStatusChecker::Init()
{
	// Initialization logic, if necessary (e.g., logging)
	return true;
}

uint32 FPortalStatusChecker::Run()
{
	// Main loop of the thread, runs until Stop() is called
	while (bShouldRun)
	{
		USkyPortalSubsystem* subref = Cast<USkyPortalSubsystem>(SkyPortalSubsystemRef);
		if (subref && !(subref->bShouldPauseRunner)) {
			// Check the portal status
			CheckPortalStatus();
		}

		// Sleep for the specified interval
		FPlatformProcess::Sleep(CheckInterval);
	}

	return 0;  // Exit code for the thread
}

void FPortalStatusChecker::Stop()
{
	// Signal the thread to stop running
	bShouldRun = false;
}

void FPortalStatusChecker::Exit()
{
	// Cleanup after the thread has stopped
}

void FPortalStatusChecker::CheckPortalStatus()
{
	// Ensure the subsystem is valid
	if (SkyPortalSubsystemRef && Cast<USkyPortalSubsystem>(SkyPortalSubsystemRef))
	{
		USkyPortalSubsystem* subref = Cast<USkyPortalSubsystem>(SkyPortalSubsystemRef);
		USkyPortalIO* PortalHandleRef = subref->PortalHandle;
		UE_LOG(LogSkyportalIO, VeryVerbose, TEXT("Check portal"));
		if (PortalHandleRef && PortalHandleRef->bPortalReady)
		{
			// Call the subsystem function to get portal status
			uint8* output = PortalHandleRef->Read();
			EPortalCommand CommandResponse = GetPortalCommandFromChar(output[0]);
			//UFigureData figData;
			switch (CommandResponse)
			{
			case S:
				CurrentStatusData = ParsePortalStatus(output);
				UE_LOG(LogSkyportalIO, VeryVerbose, TEXT("Output Data: %s"), *BytesToHex(output, sizeof(output)));

				//Send delegate when new informations are received
				if (OldStatusData != CurrentStatusData) {


					for (int i = 0; i < CurrentStatusData.StatusArray.Num(); i++) {
						if (CurrentStatusData.StatusArray[i] != OldStatusData.StatusArray[i]) {
							if (
								//!FalsePositive() //filter conflicting infos
								true) {
								int32 figID = 0;
								UFigureData* figData = NewObject<UFigureData>(); 
								//FigureDataBlock FigureData;
								switch (CurrentStatusData.StatusArray[i])
								{
								case EFigureStatus::NOT_PRESENT:
								case EFigureStatus::PRESENT:
									break;
								case EFigureStatus::ADDED:
									figData = PortalHandleRef->ReadFigureBlocks(i);
									if (figData)
									{
										figID = figData->GetFigureID();
									}
									subref->OnSkylanderAdded.Broadcast(figID, i);
									break;
								case EFigureStatus::REMOVED:
									subref->OnSkylanderRemoved.Broadcast(00, i);
									break;
								}
							}
						}
					}
					OldStatusData = CurrentStatusData;
					subref->StatusData = CurrentStatusData;
				}
				break;
			default:
				return;
			}

			// Do something with the status (log, notify, etc.)
			UE_LOG(LogSkyportalIO, VeryVerbose, TEXT("Portal Status:"));
		}

	}
}