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

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

/** Debug Inputs */
#define INPUT_NULL        (inputbind_t)0x00
#define INPUT_DEBUG_UP    (inputbind_t)0x01
#define INPUT_DEBUG_DOWN  (inputbind_t)0x02
#define INPUT_DEBUG_LEFT  (inputbind_t)0x03
#define INPUT_DEBUG_RIGHT (inputbind_t)0x04
#define INPUT_DEBUG_RAISE (inputbind_t)0x05
#define INPUT_DEBUG_LOWER (inputbind_t)0x06
#define INPUT_DEBUG_FINE  (inputbind_t)0x07
#define INPUT_DEBUG_PLUS  (inputbind_t)0x08
#define INPUT_DEBUG_MINUS (inputbind_t)0x09

/** Real Inputs (Starts at 128/0x80) */
#define INPUT_UP          (inputbind_t)0x80
#define INPUT_DOWN        (inputbind_t)0x81
#define INPUT_LEFT        (inputbind_t)0x82
#define INPUT_RIGHT       (inputbind_t)0x83


#define INPUT_BIND_COUNT 0xFF
#define INPUT_SOURCE_COUNT 4096

/**
 * Input Bind, a specific action bind reference for the game engine to use.
 * e.g. "Jump" or "Walk Forward".
 */
typedef uint8_t inputbind_t;

/**
 * Input source identifier. It's up to the platform itself to decide what the
 * hell this number refers to. For most platforms it will be an input, such as a
 * keyboard scancode or a (pad number * button count) + button.
 */
typedef uint32_t inputsource_t;

/**
 * Value that represents the state of an input. Defined as 0-1 where 0 is set
 * to be completely off / netural state, and 1 is completely on / full state.
 */
typedef float inputval_t;

/**
 * Structure for the entire input mapping.
 */
typedef struct {
  /** Float of the input between 0 and 1. */
  inputval_t inputsA[INPUT_BIND_COUNT];
  /** Float of the input between 0 and 1. */
  inputval_t inputsB[INPUT_BIND_COUNT];

  /** Flippable state */
  inputval_t *current, *previous;

  /**
   * Binding Map, Array of lists where index = binding and entry is a list of
   * input sources.
   */
  list_t *bindMap[INPUT_BIND_COUNT];

  /**
   * Input buffer array. Keeps track of raw values from the inputs.
   * The engine will read from the buffer when necessary.
   */
  inputval_t buffer[INPUT_SOURCE_COUNT];

  /** Float of the GameTime that the input was actuated last. */
  float times[INPUT_BIND_COUNT];
} input_t;