/* 
 * File:   locomotion.h
 * Author: Christian
 *
 * Created on 8 de julio de 2019, 10:59
 */

#ifndef LOCOMOTION_H
#define	LOCOMOTION_H

/*====Sistema de lista de espera====
 * Permite programar acciones para 
 * que se realizen consecutivamente,
 * esperando a que transcurra un 
 * periodo de tiempo entre cada una.
 */
/**
 * Objeto de lista de espera. 
 * Alamacena:
 *  el tiempo de espera para una accion (ms),
 *  la accion que va a desencadenar (ha de ser programada en to_do_list.c)
 *  el estado de la accion
 *  ()siguiente accion de la lista 
 *  ()anterior accion de la lista
 */
typedef struct WAITLIST_OBJ_STRUCT{
    uint32_t time;
    ACTIONLISTS al;
    unsigned char estado;
    struct WAITLIST_OBJ_STRUCT *next;
    struct WAITLIST_OBJ_STRUCT *prev;
}WL_OBJ;
/**
 * @Description
 * Inicializa los objetos de la lista de espera.
 */      
void WL_init(void);
/**
 * @Description 
 * Guarda un objeto en la lista de objetos vacios.
 */
void WL_emptyPush(WL_OBJ* newEmp);
/**
 * @Description 
 * Extrae un objeto en la lista de objetos vacios.
 */
WL_OBJ* WL_emptyPop(void);

/**
 * @Description 
 * Busca un objeto en la lista de objetos activos.
 */
WL_OBJ* WL_findIndex(int i);
/**
 * @Description 
 * Inserta un objeto entre un objeto activo y su siguiente.
 */
void WL_insert(WL_OBJ *new, WL_OBJ *cur);

/**
 * @Description 
 * Borra todos los objetos de la lista de espera.
 */
void WL_deleteAllMilestones();
/**
 * @Description 
 * Inicializar un objeto vacio (si hay disponible) e insertarlo en la posicion 
 * correcta en la lista de objetos activos. Si un objeto describe una accion con
 * con un tiempo de espera menor que alguno de los ya presentes en la lista, se 
 * inserta en la posicion adecuada. 
 * Los objetos no se aņaden al final de la lista segun se activan, apliando los 
 * tiempos de espera. En lugar de ello se ordenan segun la duracion del nuevo y 
 * el tiempo de espera restante de los demas objetos.
 */
void WL_registerMileStone(uint32_t time, ACTIONLISTS al, unsigned char estado);

/**
 * @Description 
 * Comprueba si se ha cumplido el tiempo de espera para el siguiente objeto
 */
void Time_watch(void);

/*====Sistema de lista de distancia====
 * Permite programar acciones para 
 * que se realizen consecutivamente,
 * esperando a que el robot recorra
 * una distancia entre cada una.
 */
/**
 * Objeto de lista de espera. 
 * Alamacena:
 *  distancia a recorrer para realizar una accion (ms),
 *  la accion que va a desencadenar (ha de ser programada en to_do_list.c)
 *  el estado de la accion
 *  ()siguiente accion de la lista 
 *  ()anterior accion de la lista
 */
typedef struct DISTANCEWAITLIST_OBJ_STRUCT{
    int32_t distance;
    ACTIONLISTS al;
    unsigned char estado;
    struct DISTANCEWAITLIST_OBJ_STRUCT *next;
    struct DISTANCEWAITLIST_OBJ_STRUCT *prev;
}DWL_OBJ;

/**
 * @Description
 * Inicializa los objetos de la lista de espera.
 */    
void DWL_init(void);
/**
 * @Description 
 * Guarda un objeto en la lista de objetos vacios.
 */
void DWL_emptyPush(DWL_OBJ* newEmp);
/**
 * @Description 
 * Extrae un objeto en la lista de objetos vacios.
 */
DWL_OBJ* DWL_emptyPop(void);

/**
 * @Description 
 * Busca un objeto en la lista de objetos activos.
 */
DWL_OBJ* DWL_findIndex(int i);
/**
 * @Description 
 * Inserta un objeto entre un objeto activo y su siguiente.
 */
void DWL_insert(DWL_OBJ *new, DWL_OBJ *cur);
/**
 * @Description 
 * Borra todos los objetos de la lista de espera.
 */
void DWL_deleteAllMilestones();
/**
 * @Description 
 * Inicializar un objeto vacio (si hay disponible) e insertarlo en la posicion 
 * correcta en la lista de objetos activos. Si un objeto describe una accion con
 * con un tiempo de espera menor que alguno de los ya presentes en la lista, se 
 * inserta en la posicion adecuada. 
 * Los objetos no se aņaden al final de la lista segun se activan, apliando los 
 * tiempos de espera. En lugar de ello se ordenan segun la duracion del nuevo y 
 * el tiempo de espera restante de los demas objetos.
 */
void DWL_registerMileStone(int32_t time, ACTIONLISTS al, unsigned char estado);

/**
 * @Description 
 * Comprueba si se ha recorrido la distancia para el siguiente objeto.
 */
void Locomotion_watch();

extern volatile int32_t *distanceWatch;

/**
  @Summary
    Programa una rotacion en la direccion y sentido seleccionados.
  @Description
    Hace girar al robot 'arc' fracciones de revolucion x veces en el sentido y 
    direccion seleccionados. 
  @Param
    int x = Repeticiones.
    int arc = Fracciones de revolucion (si arc == 2 -> completar 1/2 vuelta).
    char direction = Sentido y direccion del giro.
        1 izquierda
        2 derecha 
        + adelante
        - atras
*/
void rotate_x_laps(int x, int arc, char direction);
void rotate_x_laps2(int x, int arc, char direction);
/**
  @Summary
    Programa el recorrido de una distancia.
  @Description
    Hace que el robot recorra X cm a una velocidad seleccionada. 
  @Param
    int32_t x = Distancia en cm.
    double speed = Velocidad en cm/s.
*/
void go_x_cms(int32_t x, double speed);
void go_x_cms2(int32_t x);



#endif	/* LOCOMOTION_H */

