#ifndef __Rig_h__
#define __Rig_h__

#include "RigState.h"

enum UpdateSource {
  NoSource,
  RaduinoSource,
  CATSource  
};

class UBitxRig {
  public:
  inline void begin() {}
  inline void update() {}
  inline unsigned long getFreqA() const { return state.vfo[0]; }
  inline unsigned long getFreqB() const { return state.vfo[1]; }
  inline long getRIT() const { return state.rit; }
  inline long getXIT() const { return state.xit; }
  inline bool isVFOA() const { return (state.flags & UBITX_VFOB_FLAG) != UBITX_VFOB_FLAG; }
  inline bool isVFOB() const { return (state.flags & UBITX_VFOB_FLAG) == UBITX_VFOB_FLAG; }
  inline bool isSplit() const { return (state.flags & UBITX_SPLIT_FLAG) == UBITX_SPLIT_FLAG; }
  inline bool isRITOn() const { return (state.flags & UBITX_RIT_FLAG) == UBITX_RIT_FLAG; }
  inline bool isXITOn() const { return (state.flags & UBITX_XIT_FLAG) == UBITX_XIT_FLAG; }
  inline bool isCW() const { return (state.flags & UBITX_CW_FLAG) == UBITX_CW_FLAG; }
  inline bool isLSB() const { return (state.flags & UBITX_USB_FLAG) != UBITX_USB_FLAG; }
  inline bool isUSB() const { return (state.flags & UBITX_USB_FLAG) == UBITX_USB_FLAG; }
  inline bool getAI() const { return autoInfo; }
  inline bool updatedByCAT() const { return lastUpdatedBy == CATSource; }
  inline bool updatedByRaduino() const { return lastUpdatedBy == RaduinoSource; }

  inline void clearUpdate() { lastUpdatedBy = NoSource; }
  inline void setRaduinoUpdate() { lastUpdatedBy = RaduinoSource; }
  inline void setCATUpdate() { lastUpdatedBy = CATSource; }

  inline void setFreqA(unsigned long freq, bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.vfo[0] = freq;
  }
  
  inline void setFreqB(unsigned long freq, bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.vfo[1] = freq;
  }

  inline void setRIT(short offset, bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.rit = offset;
  }

  inline void setXIT(short offset, bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.xit = offset;
  }

  inline void selectVFOA(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_VFOB_FLAG;
  }

  inline void selectVFOB(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_VFOB_FLAG;
  }

  inline void toggleVFO(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags ^= UBITX_VFOB_FLAG;
  }

  inline void splitOn(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_SPLIT_FLAG;
  }

  inline void splitOff(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_SPLIT_FLAG;
  }

  inline void ritOn(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_RIT_FLAG;
  }

  inline void ritOff(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_RIT_FLAG;
  }
  
  inline void xitOn(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_XIT_FLAG;
  }

  inline void xitOff(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_XIT_FLAG;
  }

  inline void cwOn(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_CW_FLAG;
  }

  inline void cwOff(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_CW_FLAG;
  }

  inline void selectLSB(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags &= ~UBITX_USB_FLAG;
  }

  inline void selectUSB(bool isCAT = false) {
    lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
    state.flags |= UBITX_USB_FLAG;
  }

  inline void aiOn() { autoInfo = true; }
  inline void aiOff() { autoInfo = false; }

  uint8_t* const stateAsBytes() const { return (uint8_t* const)&state; }

  inline void updateState(UBitxRigState& r, bool isCAT = false) {
    if ((r.vfo[0] == state.vfo[0]) &&
        (r.vfo[1] == state.vfo[1]) &&
        (r.rit == state.rit) &&
        (r.xit == state.xit) &&
        (r.flags == state.flags)) {
          return;
        } else {
          state = r;
          lastUpdatedBy = isCAT ? CATSource : RaduinoSource;
        }
  }

  private:
  bool autoInfo = false;
  UpdateSource lastUpdatedBy = NoSource;  
  UBitxRigState state;
};

extern UBitxRig Rig;

#endif
