//-----------------------------------------------------------------------------
///
/// \brief  Class representing an GPIO
///
/// \date   20121107
/// \author Maximilian Seesslen <development.seesslen.net>
///
//-----------------------------------------------------------------------------


//---Includes------------------------------------------------------------------


#include <biwak/biwak.h>      // exception
#include <biwak/gpio.hpp>
#include <lepto/log.h>
#include <lepto/lepto.h>      // address_t

#include <biwak/linux/boardgui.h>
#include "ui_boardgui.h"
#include <biwak/linux/gpio_mode_enums.hpp>

//#include <QGridLayout>
#include <QAbstractButton>

//---Implementation------------------------------------------------------------


struct SGpioMode
{
   const EGpioMode mode;
};


class CGpioDimpl
{
   friend class CGpio;
   
   private:
      QAbstractButton* m_button=nullptr;

   public:
      CGpioDimpl( const char* label, const SGpioMode &gpioMode )
      {
         CBoardGui *gui=CBoardGui::instance();

      if(gui)
      {
         switch(gpioMode.mode)
         {
            case EGpioMode::None:
               break;
            case EGpioMode::Input:
            case EGpioMode::InputFloating:
               m_button=gui->createInput();
               break;
            case EGpioMode::Output:
               m_button=gui->createOutput();
               break;
            case EGpioMode::Led:
               m_button=gui->createOutput();
               break;
            case EGpioMode::Button:
               m_button=gui->createOutput();
               break;
            // case EGpioMode::AfMin ... EGpioMode::AfMax: does not compile on debian buster; compiler segfaults
            case EGpioMode::AfMin:
               break;
            case EGpioMode::Pwm:
               break;
            case EGpioMode::AfMax:
               break;
            case EGpioMode::Analog:
               break;
            default:
               break;
         }
            
         m_button->setText( QString("%1").arg(label) );
      }
   }
};


//---Implementation------------------------------------------------------------


CGpio::CGpio(EGpioPeripheral _eGpioPeripheral, EGpioPin _eGpioPin
          , const SGpioMode &gpioMode, int altFunc)
    :CGpio( "???", gpioMode, altFunc)
{
   m_eGpioPeripheral=_eGpioPeripheral;
   m_eGpioPin=_eGpioPin;
}


CGpio::CGpio( const char* label
          , const SGpioMode &gpioMode, int altFunc)

{
   m_value=false;
   m_pDimpl=new CGpioDimpl( label, gpioMode );
   return;
};


CGpio::~CGpio() /**/
{
   return;
};


int CGpio::init( EGpioPeripheral eGpioPeripheral, EGpioPin eGpioPin
         , const SGpioMode &gpioMode /*=gpioModeInput*/, int altFunc /*=0*/ ) /* static */
{
   return(0);
}


void CGpio::setValue(bool value)
{
   m_value=value;

   if(m_pDimpl->m_button)
   {
      m_pDimpl->m_button->setChecked(m_value);
      if( !m_pDimpl->m_button->isCheckable() )
      {
         lFatal("Setting output widget to value which can not be checked.");
      }
   }
   
   if( getValue() != value )
   {
      lFatal("Setting output does not change anything.");
   }

   return;
};


bool CGpio::getValue() const
{
   if( m_pDimpl->m_button )
   {
      return( m_pDimpl->m_button->isChecked() || m_pDimpl->m_button->isDown() );
   }
   return( m_value );
}


//---fin-----------------------------------------------------------------------
