#include "UDPInstanceSubsystem.h"
#include "Serialization/JsonReader.h"
#include "Serialization/JsonWriter.h"
#include "Sockets.h"
#include "Camera/CameraComponent.h"
#include "Common/UdpSocketBuilder.h"
#include "Common/UdpSocketReceiver.h"
#include "GameFramework/Pawn.h"
#include "Kismet/KismetMathLibrary.h"

TSharedPtr<FJsonObject> FDeviceData::ToJsonObject() const
{
    TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
    JsonObject->SetStringField("id", ID);
    JsonObject->SetNumberField("x", X);
    JsonObject->SetNumberField("y", Y);
    JsonObject->SetNumberField("z", Z);
    JsonObject->SetNumberField("yaw", Yaw);
    JsonObject->SetNumberField("roll", Roll);
    JsonObject->SetNumberField("pitch", Pitch);
    return JsonObject;
}

bool FDeviceData::FromJsonObject(const TSharedPtr<FJsonObject>& JsonObject, FDeviceData& OutDeviceData)
{
    if (!JsonObject.IsValid())
        return false;

    if (!JsonObject->TryGetStringField("id", OutDeviceData.ID))
        return false;

    if (!JsonObject->TryGetNumberField("x", OutDeviceData.X))
        return false;

    if (!JsonObject->TryGetNumberField("y", OutDeviceData.Y))
        return false;

    if (!JsonObject->TryGetNumberField("z", OutDeviceData.Z))
        return false;

    if (!JsonObject->TryGetNumberField("yaw", OutDeviceData.Yaw))
        return false;

    if (!JsonObject->TryGetNumberField("roll", OutDeviceData.Roll))
        return false;

    if (!JsonObject->TryGetNumberField("pitch", OutDeviceData.Pitch))
        return false;

    return true;
}

void UUDPInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);
    InitNetwork();
    UUID = FGuid::NewGuid().ToString();
}

void UUDPInstanceSubsystem::Deinitialize()
{
    CleanupNetwork();
    Super::Deinitialize();
}

void UUDPInstanceSubsystem::InitNetwork()
{
    // 初始化发送socket
    SenderSocket = FUdpSocketBuilder(TEXT("UDPSenderSocket"))
        .AsReusable()
        .WithBroadcast();

    // 设置远程端点 (192.168.1.28:1234)
    FIPv4Address::Parse(TEXT("192.168.111.254"), RemoteEndpoint.Address);
    RemoteEndpoint.Port = 1234;

    // 初始化接收socket
    ReceiverSocket = FUdpSocketBuilder(TEXT("UDPReceiverSocket"))
        .AsReusable()
        .WithBroadcast()
        .BoundToEndpoint(FIPv4Endpoint(FIPv4Address::Any, 9999)) // 监听相同端口
        .WithReceiveBufferSize(65535);

    // 启动接收线程
    SocketReceiver = new FUdpSocketReceiver(ReceiverSocket, FTimespan::FromMilliseconds(100), TEXT("UDPReceiver"));
    SocketReceiver->OnDataReceived().BindUObject(this, &UUDPInstanceSubsystem::OnDataReceived);
    SocketReceiver->Start();
}

void UUDPInstanceSubsystem::CleanupNetwork()
{
    // 停止接收线程
    if (SocketReceiver)
    {
        SocketReceiver->Stop();
        delete SocketReceiver;
        SocketReceiver = nullptr;
    }

    // 关闭接收socket
    if (ReceiverSocket)
    {
        ReceiverSocket->Close();
        ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ReceiverSocket);
        ReceiverSocket = nullptr;
    }

    // 关闭发送socket
    if (SenderSocket)
    {
        SenderSocket->Close();
        ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(SenderSocket);
        SenderSocket = nullptr;
    }
}

void UUDPInstanceSubsystem::SetTrackedPawn(APawn* NewPawn)
{
    TrackedPawn = NewPawn;
}

void UUDPInstanceSubsystem::SendDeviceData(const FDeviceData& DeviceData)
{
    if (!SenderSocket)
        return;

    // 将结构体转换为JSON
    TSharedPtr<FJsonObject> JsonObject = DeviceData.ToJsonObject();
    FString JsonString;
    TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
    FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);

    // 发送数据
    TArray<uint8> Data;
    FTCHARToUTF8 Converter(*JsonString);
    Data.Append((uint8*)Converter.Get(), Converter.Length());
    
    int32 BytesSent = 0;
    SenderSocket->SendTo(Data.GetData(), Data.Num(), BytesSent, RemoteEndpoint.ToInternetAddr().Get());
}

void UUDPInstanceSubsystem::SendCurrentPawnData()
{
    if (!TrackedPawn)
        return;

    FDeviceData DeviceData;
    /*DeviceData.ID = "PlayerPawn";*/
    DeviceData.ID = UUID;
    UCameraComponent* TargetCamera = TrackedPawn->FindComponentByClass<UCameraComponent>();

    FVector Location = TargetCamera->GetComponentLocation();
    DeviceData.X = Location.X;
    DeviceData.Y = Location.Y;
    DeviceData.Z = 0;
    
    FRotator Rotation = TargetCamera->GetComponentRotation();
    DeviceData.Yaw = Rotation.Yaw;
    DeviceData.Roll = Rotation.Roll;
    DeviceData.Pitch = Rotation.Pitch;
    
    /*FVector Location = TrackedPawn->GetActorLocation();
    DeviceData.X = Location.X;
    DeviceData.Y = Location.Y;
    DeviceData.Z = Location.Z;
    
    FRotator Rotation = TrackedPawn->GetActorRotation();
    DeviceData.Yaw = Rotation.Yaw;
    DeviceData.Roll = Rotation.Roll;
    DeviceData.Pitch = Rotation.Pitch;*/

    SendDeviceData(DeviceData);
}


void UUDPInstanceSubsystem::SpawnActorInGameThread(TSubclassOf<AActor> Actor, const FVector& Location, const FRotator& Rotation, const FString& ID, FOnActorSpawned OnActorSpawned)
{
    // 强制要求在 GameThread 调用
    if (IsInGameThread())
    {
        UE_LOG(LogTemp, Error, TEXT("In main thread"));
        return;
    }
    // 记录开始创建
    UE_LOG(LogTemp, Log, TEXT("Actor1111 "));

    // 使用智能指针或委托机制才能安全地处理异步结果
    AsyncTask(ENamedThreads::GameThread, [this, Location, Rotation, ID, Actor, OnActorSpawned]()
    {
        if (!GetWorld())
        {
            UE_LOG(LogTemp, Error, TEXT("Cannot spawn actor: invalid world"));
            OnActorSpawned.ExecuteIfBound(nullptr, ID);
            return;
        }

        if (!Actor)
        {
            UE_LOG(LogTemp, Error, TEXT("Cannot spawn actor: invalid actor class"));
            OnActorSpawned.ExecuteIfBound(nullptr, ID);
            return;
        }

        AActor* NewActor = GetWorld()->SpawnActor<AActor>(Actor, Location, Rotation);
        if (NewActor)
        {
            UE_LOG(LogTemp, Log, TEXT("Actor %s spawned at %s"), ID.Len() ? *ID : TEXT("Unknown"), *Location.ToString());
        }
        else
        {
            UE_LOG(LogTemp, Warning, TEXT("Failed to spawn actor %s"), *ID);
        }

        OnActorSpawned.ExecuteIfBound(NewActor, ID);
    });
}

void UUDPInstanceSubsystem::OnDataReceived(const FArrayReaderPtr& ArrayReaderPtr, const FIPv4Endpoint& EndPt)
{
    // 将接收到的二进制数据转换为字符串
    uint8* Data = (uint8*)ArrayReaderPtr->GetData();
    int32 DataSize = ArrayReaderPtr->Num();
    
    // 添加字符串结束符
    TArray<uint8> DataWithNull;
    DataWithNull.Append(Data, DataSize);
    DataWithNull.Add(0); // 添加null终止符
    
    // 转换为FString
    FString DataString = UTF8_TO_TCHAR(DataWithNull.GetData());

    ParseReceivedData(DataString);
    
    // 在游戏线程中处理数据
    // AsyncTask(ENamedThreads::GameThread, [this, DataString]() {
    //     
    // });
}

void UUDPInstanceSubsystem::ParseReceivedData(const FString& DataString)
{
    //UE_LOG(LogTemp, Warning, TEXT("Received Data: %s"), *DataString);

    TMap<FString, FDeviceData> DeviceDataMap;

    TSharedPtr<FJsonObject> JsonObject;
    TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(DataString);
    if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
    {
        for (const auto& Pair : JsonObject->Values)
        {
            if (Pair.Value.IsValid() && Pair.Value->Type == EJson::Object)
            {
                FDeviceData DeviceData;
                if (FDeviceData::FromJsonObject(Pair.Value->AsObject(), DeviceData))
                {
                    DeviceData.ID = Pair.Key; // Set ID from map key
                    DeviceDataMap.Add(Pair.Key, DeviceData);
                }
            }
        }
    }

    FDeviceDataMap DeviceDataMapStruct;
    DeviceDataMapStruct.ReceivedDataMap = DeviceDataMap;
    AsyncTask(ENamedThreads::GameThread, [&,this,  DeviceDataMapStruct]()
    {
        OnDeviceDataReceived.Broadcast(DeviceDataMapStruct);
    });
}