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

#pragma once
#include "../../libs.h"

/** Maximum number of actions a timeline can support, smaller than 0xFF */
#define TIMELINE_ACTION_COUNT_MAX 128

/** Type forwarders */
typedef struct _timeline_t timeline_t;
typedef struct _timelineaction_t timelineaction_t;

/**
 * Callback for when a timeline event occurs
 * @param timeline The timeline that fired this callback.
 * @param action The action that this callback is attached to.
 * @param i The index that this action is within the timeline.
 */
typedef void timelinecallback_t(timeline_t *timeline, timelineaction_t *action,
  uint8_t i
);

typedef struct _timelineaction_t {
  /** Pointer to any custom user data the timeline action wants to use. */
  void *data;

  /**
   * The time that this action should occur within the timeline
   * set to 0 or less to start immediately.
   */
  float start;

  /**
   * The duration of the action, this will decide for how long onDuration will
   * be called for, and when onEnd should be called.
   * Set to a negative number to have this continue forever.
   * Set to 0 to only fire the onStart. 
   * onStart can fire with either onDuration and onEnd on the same frame, but
   * onEnd and onDuration cannot fire the same frame.
   */
  float duration;

  /**
   * Enables animation looping. This works by forcing start to be equal to the
   * current time at the point in time that onEnd is called. This will also stop
   * onStart being called so ensure that your onStart and onEnd logic works.
   */
  bool loop;

  timelinecallback_t *onStart;
  
  timelinecallback_t *onDuration;

  timelinecallback_t *onEnd;
} timelineaction_t;

typedef struct _timeline_t {
  /** The current time as far as the timeline is concerned */
  float current;
  
  /** The time of the last "frame" as far as the timeline is concerned */
  float previous;

  /** The frame time diff, essentially current = previous + diff */
  float diff;

  /** User pointer, allows you to point to some other data */
  void *user;

  /** Actions within the timeline */
  timelineaction_t actions[TIMELINE_ACTION_COUNT_MAX];
  uint8_t actionCount;
} timeline_t;