
#ifndef EngraveCube_h
#define EngraveCube_h
#endif

#include <stdlib.h>
#include <AccelStepper.h>
#include "config.h"

#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#include <wiring.h>
#endif

/*! Classe di controllo del dispositivo Engrave Cube.
 *
 *  La CLasse $name reppresenta il dispositivo nel suo complesso e consente di
 *  leggere ed interpretare (parse) i conadi Gcode forniti e di controllare
 *  l'elettronica e la meccanica dell'apparato.
 */
class EngraveCube {

  public:

    // typedef enum name {
    //   DIR_CW = 1,
    //   DIR_CCW = -1
    // } DIRECTION;

    // Nomi simbolici per le modalità di calcolo dei movimenti.
    // ABSOLUTE: i comandi di movimento saranno interpretati in maniera maniera
    //           assoluta (rispetto all'origine degli assi).
    // RELATIVE: i comandi di movimento saranno interpretati in maniera maniera
    //           relativa (rispetto alla posizione attuale).
    typedef enum {
      ABSOLUTE = 1,
      RELATIVE = 0
    } positioningMode;

    /*! Costruttore di classe
    *
    * Inizializza l'oggetto di controllo con i parametri di default conetnuti
    * nel file di configurazione.
    */
    EngraveCube();

    /*! Il metodo interpreta ed esegue il comando G-Code fonito in input.
    *   \param cmdBuffer Vettore di caratteri contenete il comndo letto dalla
    *   seriale.
    *   \param cmdLng Numero di caratteri del comando G-Code.
    *   \return Stringa con l'esito dell'esecuzione del comendo da
    *   ritrasmettere sulla seriale.
    */
    char* parse(char cmdBuffer[], int cmdLng);

    boolean isRunning();

    void run();

  private:

    void EngraveCube::goToXY(float x, float y, float speed = NULL);

    bool EngraveCube::setSpeed(float speed);

    bool EngraveCube::setAccel(float accel);

    /*! Consente di impostare la potenza del laser.
     *
     *  Consente di impostare la potenza del laser su una scala da 0 (spento) a
     *  255 (massima potenza).
     *  \param lsrPwr Valore intero tra 0 e 255 che indica la potenza di
     *  attivazione del laser.
     */
    void EngraveCube::setLaserPwr(int lsrPwr);

    void EngraveCube::runSpeed();

   /*! Converte millimetri in step.
    *
    *  Il metodo consente di convertire millimetri in step sulla base di un
    *  fattore di conversione fornito. Viene impiegato nell'esecuzione di
    *  tutti comandi G-code di movimento per istruire la libreria AccelStepper
    *  sull'entità del movimento da effettuare.
    *
    *  \param stp4mm fattore di conversione mm -> step
    *  \param mm numero di mm da convertire.
    *  \return numero di steps
    */
    float EngraveCube::mmToStp(float stp4mm, float mm);

    boolean getEndstopX();

    boolean getEndstopY();

    // Recupera il valore di un parametro G-Code se specificato nel comando
    // Es. Per il comando 'G0 X100 Y200' la chiamata getParamVal('X', valX)
    // Restituisce TRUE ed imposta valX a 100.0
    boolean getParamVal(char key, double* value);

    /*===========================================================
                            Comandi G-Code implementati.
    =============================================================*/

    // G0: Movimento lineare rapido
    char* EngraveCube::cmdG0();

    // G28: Homing
    char* EngraveCube::cmdG28();

    // G90: Imposta posizionamento assoluto.
    char* EngraveCube::cmdG90();

    // G91: Imposta posizionamento relativo.
    char* EngraveCube::cmdG91();


    /*===========================================================
                              Variabili di stato.
    =============================================================*/

    // Posizione in steps dello stepper X
    AccelStepper _stepperX;

    // Posizione in steps dello stepper Y
    AccelStepper _stepperY;

    // Ultima velocità impostata
    float _speed;

    // Ultimo comando
    char *_cmdBuffer;

    // Lunghezza (in caratteri) del comando in elaborazione.
    int _cmdBufLng;

    // Modalità di calcolo dei movimenti (ABSOLUTE/Relative).
    bool _positioning;

    // Last laser power value
    int _lsrPwr;
};
