#pragma once

#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingBasics.h"
#include "Misc/Paths.h"
#include "Misc/PackageName.h"
#include "FileHelpers.h"
#include "HAL/FileManager.h"
#include "UObject/LinkerLoad.h"
#include "Asset_Restore.generated.h"


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------

UCLASS()
class UWing_Asset_Restore : public UWingHandler
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, meta=(Description="Asset to restore"))
	FString Asset;

	virtual void Register() override
	{
		UWingServer::AddHandler(this,
			TEXT("Restore a .uasset file from its .uasset.bak backup, reloading it in the editor."));
	}
	virtual void Handle() override
	{
		FString Filename = FPaths::ConvertRelativePathToFull(
			FPackageName::LongPackageNameToFilename(Asset, FPackageName::GetAssetPackageExtension()));
		FString BackupFilename = Filename + TEXT(".bak");

		if (!IFileManager::Get().FileExists(*BackupFilename))
		{
			WingOut::Stdout.Printf(TEXT("ERROR: Backup file not found: %s\n"), *BackupFilename);
			return;
		}

		// Release file handles if the package is loaded
		UPackage* Package = FindPackage(nullptr, *Asset);
		if (Package)
		{
			ResetLoaders(Package);
		}

		// Copy backup over the original
		uint32 CopyResult = IFileManager::Get().Copy(*Filename, *BackupFilename, true);
		if (CopyResult != COPY_OK)
		{
			WingOut::Stdout.Printf(TEXT("ERROR: Failed to copy backup over %s\n"), *Asset);
			return;
		}

		// Reload the package if it was loaded
		if (Package)
		{
			bool bReloaded = false;
			FText ErrorMessage;
			UEditorLoadingAndSavingUtils::ReloadPackages({Package}, bReloaded, ErrorMessage, EReloadPackagesInteractionMode::AssumePositive);
			if (!bReloaded)
			{
				WingOut::Stdout.Printf(TEXT("WARNING: Restored %s but reload failed: %s\n"),
					*Asset, *ErrorMessage.ToString());
				return;
			}
		}

		WingOut::Stdout.Printf(TEXT("Restored %s from backup\n"), *Asset);
	}
};
