// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.

#include "WidgetInteraction.h"
#include "HeadMountedDisplayFunctionLibrary.h"
#include "IDisplayCluster.h"
#include "IDisplayClusterClusterManager.h"
#include "Engine.h"

#define LOCTEXT_NAMESPACE "FWidgetInteractionModule"

void FWidgetInteractionModule::StartupModule()
{
  on_world_tick_start_delegate_.BindRaw(this, &FWidgetInteractionModule::OnWorldTickStart);
  FWorldDelegates::OnWorldTickStart.Add(on_world_tick_start_delegate_);
}

void FWidgetInteractionModule::ShutdownModule()
{
}


void FWidgetInteractionModule::OnWorldTickStart(ELevelTick level_tick, float val)
{
  //called every Tick()

  auto worlds = GEngine->GetWorldContexts();

  for (auto world_context : worlds) {

    auto world = world_context.World();

    if (last_world == world  && widget_interaction_cmp_ != nullptr) {
      if (widget_interaction_cmp_->IsValidLowLevel() == true) {
        continue;
      }
      else {
        widget_interaction_cmp_ = nullptr;
      }
    }

    if (world == nullptr)
      continue;

    auto player_controller = world->GetFirstPlayerController();
    if (player_controller == nullptr)
      continue;

    auto vr_pawn = dynamic_cast<AVirtualRealityPawn*>(player_controller->AcknowledgedPawn);
    if (vr_pawn == nullptr)
      continue;

    UE_LOG(LogTemp, Warning, TEXT("OnWorldTickStart called and interaction component will be updated"));

    FString name = "";
    UClass* component_class = UMotionControllerComponent::StaticClass();


    if (IDisplayCluster::Get().GetClusterMgr()->IsStandalone()) {
      //if this is a standalone setup ...
      if (UHeadMountedDisplayFunctionLibrary::IsHeadMountedDisplayEnabled()) {
        //.. with an HMD, we attach the intercation component to the right hand
        name = FString("RightMotionController");
        component_class = UMotionControllerComponent::StaticClass();
      }
      else {
        //... without an HMD, we also attach it to the virtual right hand, since it exists in this case
        name = TEXT("RightMotionController");
        component_class = UMotionControllerComponent::StaticClass();
      }
    }
    else {
      //if this is a cluster setup we attach it to the flystick
      name = TEXT("flystick");
      component_class = UMotionControllerComponent::StaticClass();
    }

    auto parent_vec = vr_pawn->GetComponentsByClass(component_class);
    bool success;
    for (auto parent : parent_vec) {
      if (parent->GetName() == FString(name)) {
        CreateWidgetInteraction(dynamic_cast<USceneComponent*>(parent), vr_pawn);
        success = true;
        last_world = world;
      }
    }

    if (!success)
      UE_LOG(LogTemp, Error, TEXT("Failed to load widget asset \"%s"), *name);
  }
}

void FWidgetInteractionModule::CreateWidgetInteraction(USceneComponent * parent, AVirtualRealityPawn* outer)
{
  widget_interaction_cmp_ = NewObject<URwthComponent>(outer, URwthComponent::StaticClass());
  widget_interaction_cmp_->AttachToComponent(parent, FAttachmentTransformRules(EAttachmentRule::KeepRelative, false));
  widget_interaction_cmp_->Init();
}

#undef LOCTEXT_NAMESPACE

IMPLEMENT_MODULE(FWidgetInteractionModule, WidgetInteraction)