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

#pragma once
#include <dawn/dawn.h>
#include "../util/list.h"

/**
 * Initializes the input manager.
 * 
 * @param input The input manager to initialize.
 */
void inputInit(input_t *input);

/**
 * Tick the input manager.
 * 
 * @param input The input manager to update.
 */
void inputUpdate(input_t *input);

/**
 * Destroy the input manager and cleanup.
 * 
 * @param input The input manager to dispose.
 */
void inputDispose(input_t *input);

/**
 * Binds the given input binding to the input source. Essentially allowing any
 * time we fetch the state of bind, we will read the value from source.
 * 
 * @param input The input manager.
 * @param bind The binding to bind against.
 * @param source The source that is being bound.
 */
void inputBind(input_t *input, inputbind_t bind, inputsource_t source);

/**
 * Unbind a previously bound input source from a binding. This method is costly.
 * 
 * @param input The input manager.
 * @param bind The binding to unbind from.
 * @param source The source that is being unbound.
 */
void inputUnbind(input_t *input, inputbind_t bind, inputsource_t source);

/**
 * Is the current input "down", being pressed, being moved, not in a state
 * of rest.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return True if the input vector is non-zero.
 */
bool inputIsDown(input_t *input, inputbind_t binding);

/**
 * Is the current input "up", in a state of rest, not being actioned, moved.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return True if input vector is zero
 */
bool inputIsUp(input_t *input, inputbind_t binding);

/**
 * Returns true on the first tick that an input was actioned/downed.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return True if the input vector was non-zeroed this tick but not last. 
 */
bool inputIsPressed(input_t *input, inputbind_t binding);

/**
 * Returns true on the first tick that an input was released/upped.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return True if the input vector was zeroed this tick but not last. 
 */
bool inputIsReleased(input_t *input, inputbind_t binding);

/**
 * Returns the raw input value as a float between 0 and 1. For digital (buttons)
 * this will typicall be 0 or 1 only. Other analogue inputs will have anywhere
 * within the range.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return Input state of the axis.
 */
inputval_t inputGetAxis(input_t *input, inputbind_t binding);

/**
 * Returns a raw input value between -1 and 1 between two axis. This would be
 * indicitive of having an input with an axis that can be moved one direction
 * for a positive input and another for a negative input, typically a game
 * controller's analogue sticks.
 * 
 * @param input The input manager.
 * @param postitive The positive axis binding.
 * @param negative The negative axis binding.
 * @return A float between -1 and 1 representing the result of both.
 */
float inputGetFullAxis(input_t *input, inputbind_t positive, inputbind_t negative);

/**
 * Returns the time that an input was actuated at. Actuate would count as a
 * non-zero input for analogue inputs.
 * 
 * @param input The input manager.
 * @param binding The previously bound input binding.
 * @return Game Engine time that an input was non-zeroed
 */
float inputGetAccuated(input_t *input, inputbind_t binding);