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

#pragma once
#include "scene/SceneItemComponent.hpp"
#include "visualnovel/ui/VisualNovelTextbox.hpp"
#include "visualnovel/ui/VisualNovelFader.hpp"

namespace Dawn {
  class IVisualNovelEvent;

  class VisualNovelManager : public SceneItemComponent {
    private:
      IVisualNovelEvent* currentEvent = nullptr;

    public:
      UICanvas *uiCanvas = nullptr;
      VisualNovelTextbox *textBox = nullptr;
      VisualNovelFader *fader = nullptr;
      
      AudioSource *audioBackground = nullptr;
      AudioSource *audioCharacter = nullptr;

      /** Event listener for unpaused scene updates. */
      void onUnpausedUpdate();

      /**
       * Constructs a visual novel manager, scene item component.
       * 
       * @param item Item that the VN manager belongs to.
       */
      VisualNovelManager(SceneItem *item);

      /**
       * Sets the currently active visual novel event. This is assumed to be 
       * the only way to handle events (no multiples currently).
       * 
       * @param event Event to set.
       */
      template <class T>
      T * setEvent(T *event) {
        auto oldCurrent = this->currentEvent;
        this->currentEvent = event;
        if(this->hasInitialized && event != nullptr) event->start(oldCurrent);
        delete oldCurrent;
        return event;
      }

      /**
       * Override to the SceneItemComponent on start event.
       * 
       */
      void onStart() override;
    
      /**
       * Dispose / Cleanup the VN manager.
       * 
       */
      ~VisualNovelManager();

      friend class IVisualNovelEvent;
  };


  class IVisualNovelEvent {
    protected:
      VisualNovelManager *manager;
      IVisualNovelEvent *doNext = nullptr;
      bool_t hasStarted = false;

      virtual void onStart(IVisualNovelEvent *previous) = 0;
      virtual bool_t onUpdate() = 0;
      virtual void onEnd() = 0;

    public:
      IVisualNovelEvent(VisualNovelManager *manager);

      /**
       * Chains an event to be executed after this event has finished.
       * 
       * @param next Event to process next.
       * @return Whatever you pass in to next.
       */
      template<class T>
      T * then(T *next) {
        this->doNext = next;
        return next;
      }

      /**
       * Begins this visual novel event, internally updates some flags and 
       * calls the event to do its own start logic.
       * 
       * @param previous Previous event, this is for doing logic based chains.
       */
      void start(IVisualNovelEvent *previous);

      /**
       * Performs a tick on this event. The event can then decide whether or not
       * it has finished processing.
       * 
       * @return True if the event is still active, otherwise false.
       */
      bool_t update();
      
      /**
       * End this current event. Returns the "next event" to process. Most of
       * the events can handle this with the simple ->then() chaining, but some
       * events may chose to do complex if-style logic.
       * 
       * @return Event to run next.
       */
      IVisualNovelEvent * end();

      /**
       * Dispose the VN event.
       */
      virtual ~IVisualNovelEvent();

      friend class VisualNovelManager;
  };
}