// Copyright Epic Games, Inc. All Rights Reserved.

#include "MoALiveLink.h"
#include "MoALiveLinkSettings.h"
#include "MoALiveLinkSource.h"
#include "ILiveLinkClient.h"
#include "Features/IModularFeatures.h"
#include "TimerManager.h"

#if WITH_EDITOR
#include "MoARemapAssetBaseCustomization.h"
#include "MoARemapAssetBase.h"
#include "MoABoneMapping.h"
#include "PropertyEditorModule.h"
#include "Editor.h"
#endif

#define LOCTEXT_NAMESPACE "FMoALiveLinkModule"

void FMoALiveLinkModule::StartupModule()
{
#if WITH_EDITOR
	FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
	
	PropertyModule.RegisterCustomPropertyTypeLayout(
		FMoABoneMappingRow::StaticStruct()->GetFName(),
		FOnGetPropertyTypeCustomizationInstance::CreateStatic(&FMoABoneMappingRowCustomization::MakeInstance)
	);
	
	PropertyModule.RegisterCustomClassLayout(
		UMoARemapAssetBase::StaticClass()->GetFName(),
		FOnGetDetailCustomizationInstance::CreateStatic(&FMoARemapAssetBaseCustomization::MakeInstance)
	);
	
	PropertyModule.NotifyCustomizationModuleChanged();
	
	// Register for post engine init to auto-connect
	FCoreDelegates::OnPostEngineInit.AddRaw(this, &FMoALiveLinkModule::OnPostEngineInit);
#endif
}

void FMoALiveLinkModule::OnPostEngineInit()
{
#if WITH_EDITOR
	// Delay auto-connect to ensure LiveLink module is fully ready
	// Use a longer delay to ensure everything is initialized
	FTimerHandle TimerHandle;
	if (GEditor)
	{
		GEditor->GetTimerManager()->SetTimer(TimerHandle, [this]()
		{
			AutoConnectIfEnabled();
		}, 1.0f, false); // 1 second delay
	}
#endif
}

void FMoALiveLinkModule::AutoConnectIfEnabled()
{
#if WITH_EDITOR
	UMoALiveLinkSettings* Settings = UMoALiveLinkSettings::Get();
	if (!Settings)
	{
		UE_LOG(LogTemp, Warning, TEXT("[MoA LiveLink] Settings not available"));
		return;
	}
	
	// Load saved connections from config file
	Settings->LoadConnectionsFromConfig();
	UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] Settings loaded, %d saved connections"), Settings->SavedConnections.Num());
	
	if (!Settings->bAutoConnectOnStartup)
	{
		UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] Auto-connect disabled in settings"));
		return;
	}
	
	// Get all enabled endpoints
	TArray<FIPv4Endpoint> Endpoints = Settings->GetEnabledEndpoints();
	
	if (Endpoints.Num() == 0)
	{
		UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] No enabled connections found"));
		return;
	}
	
	UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] Attempting to auto-connect %d source(s)"), Endpoints.Num());
	
	// Get LiveLink client
	IModularFeatures& ModularFeatures = IModularFeatures::Get();
	if (!ModularFeatures.IsModularFeatureAvailable(ILiveLinkClient::ModularFeatureName))
	{
		UE_LOG(LogTemp, Warning, TEXT("[MoA LiveLink] LiveLink client not available"));
		return;
	}
	
	ILiveLinkClient& LiveLinkClient = ModularFeatures.GetModularFeature<ILiveLinkClient>(ILiveLinkClient::ModularFeatureName);
	
	// Create and add sources for each enabled endpoint
	int32 SuccessCount = 0;
	for (const FIPv4Endpoint& Endpoint : Endpoints)
	{
		FString ConnectionString = Endpoint.ToString();
		
		// Create source directly (same as MoALiveLinkSource)
		TSharedPtr<ILiveLinkSource> Source = MakeShared<MoALiveLinkSource>(Endpoint);
		
		if (Source.IsValid())
		{
			FGuid SourceGuid = LiveLinkClient.AddSource(Source);
			
			if (SourceGuid.IsValid())
			{
				UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] Auto-connected: %s"), *ConnectionString);
				SuccessCount++;
			}
			else
			{
				UE_LOG(LogTemp, Error, TEXT("[MoA LiveLink] Failed to add source for %s"), *ConnectionString);
			}
		}
	}
	
	UE_LOG(LogTemp, Log, TEXT("[MoA LiveLink] Auto-connected %d/%d sources"), SuccessCount, Endpoints.Num());
#endif
}

void FMoALiveLinkModule::ShutdownModule()
{
#if WITH_EDITOR
	FCoreDelegates::OnPostEngineInit.RemoveAll(this);
	
	if (FModuleManager::Get().IsModuleLoaded("PropertyEditor"))
	{
		FPropertyEditorModule& PropertyModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
		PropertyModule.UnregisterCustomPropertyTypeLayout(FMoABoneMappingRow::StaticStruct()->GetFName());
		PropertyModule.UnregisterCustomClassLayout(UMoARemapAssetBase::StaticClass()->GetFName());
	}
#endif
}

#undef LOCTEXT_NAMESPACE
	
IMPLEMENT_MODULE(FMoALiveLinkModule, MoALiveLink)