// Copyright (c) 2022 Dominic Masters
// 
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

#include "VisualNovelManager.hpp"
#include "visualnovel/scene/SimpleVNScene.hpp"

using namespace Dawn;

VisualNovelManager::VisualNovelManager(SceneItem *item) :
  SceneItemComponent(item)
{
}

void VisualNovelManager::onStart() {
  SceneItemComponent::onStart();

  this->uiCanvas = getScene()->findComponent<UICanvas>();
  assertNotNull(this->uiCanvas);
  
  this->textBox = this->uiCanvas->findElement<VisualNovelTextbox>();
  this->fader = this->uiCanvas->findElement<VisualNovelFader>();

  assertNotNull(this->textBox);

  this->getScene()->eventSceneUnpausedUpdate.addListener(this, &VisualNovelManager::onUnpausedUpdate);
  
  // Handle queuing simple VN Manager
  auto scene = this->getScene();
  auto sceneAsSimple = dynamic_cast<SimpleVNScene*>(scene);
  if(sceneAsSimple != nullptr) {
    this->setEvent(sceneAsSimple->getVNEvent());
  }

  if(this->currentEvent != nullptr) this->currentEvent->start(nullptr);
}

void VisualNovelManager::onUnpausedUpdate() {
  if(this->currentEvent == nullptr) return;

  if(!this->currentEvent->hasStarted) this->currentEvent->start(nullptr);
  if(this->currentEvent->update()) return;
  this->setEvent(this->currentEvent->end());
}

VisualNovelManager::~VisualNovelManager() {
  if(this->currentEvent != nullptr) {
    delete this->currentEvent;
  }
  this->getScene()->eventSceneUnpausedUpdate.removeListener(this, &VisualNovelManager::onUnpausedUpdate);
}


// // // // // // // // // // // // // // // // // // // // // // // // // // //


IVisualNovelEvent::IVisualNovelEvent(VisualNovelManager *man) {
  assertNotNull(man);
  this->manager = man;
}

void IVisualNovelEvent::start(IVisualNovelEvent *previous) {
  this->hasStarted = true;
  this->onStart(previous);
}

bool_t IVisualNovelEvent::update() {
  return this->onUpdate();
}

IVisualNovelEvent * IVisualNovelEvent::end() {
  this->onEnd();

  if(this->doNext != nullptr) {
    auto next = this->doNext;
    this->doNext = nullptr;
    return next;
  }
  return nullptr;
}

IVisualNovelEvent::~IVisualNovelEvent() {
  if(this->doNext != nullptr) delete this->doNext;
}