//----------------------------------------------------------------------------
///
/// \file   ocelli.cpp
///
/// \brief  class for handling ocelli screens
///
/// \date   20220901
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


//---Documentation------------------------------------------------------------


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


//---General--------------------------


//--- Own ----------------------------

#include <ocelli/ocelli.hpp>


//---Declaration---------------------------------------------------------------


OApp *OApp::m_globalOcelliApp=nullptr;

const CBarrelOrgan::SSlope OApp::fadeIn [] =
                                    {     {   0, brightnessOn, MSECS_PER_SEC / 4},
                                          { CBarrelOrgan::finished, 0, 0 } };

const CBarrelOrgan::SSlope OApp::fadeOut [] =
                                    {     {    brightnessOn, 0, MSECS_PER_SEC / 4 },
                                          { CBarrelOrgan::finished, 0, 0 } };


#if 0

void Ocelli::drawIcon(int x, int y, int width, int height, const char *data) /* static */
{
   CGraphicDisplay &display=OWidget::display();
}

#endif


OApp::OApp(CGraphicDisplay &display, CTouchTsc2007 *touch, CBarrelOrganFade *boBacklight,CBarrelOrganBeep *boBuzzer)
   #if defined (STM32)
   :m_boBacklight( boBacklight )
   ,m_boBuzzer( boBuzzer )
   #endif
{
   OWidget::setDisplay( display );
   #if defined (STM32)
      m_boBacklight->getPwm()->setPwmValue(0);
   #endif
   //m_pwmBacklight->setFadeMode( fadeIn );
   #if defined (STM32)
   if(touch)
   {
      touch->signalEvent.connect( this, &OApp::event );
   }
   #endif
   m_globalOcelliApp=this;
}


void OApp::setCurrentScreen(OScreen *screen)
{
   if ( m_pCurrentScreen == screen )
   {
      return;
   }

   // Dont let the "back"-button jump to stuff like alarms
   if( m_pCurrentScreen && ( m_pCurrentScreen->isSelectable() ) )
   {
      m_pPreviousScreen = m_pCurrentScreen;
   }
   m_pCurrentScreen = screen;
   #if defined (STM32)
      m_boBacklight->getPwm()->setPwmValue(0);
      m_boBuzzer->getPwm()->setPwmValue(0);
  #endif
   m_pCurrentScreen->activate();
   m_pCurrentScreen->draw();
   if(m_pNaviScreen)
   {
      m_pNaviScreen->draw();
   }
   #if defined (STM32)
      if ( m_darkened )
      {
         m_boBacklight->setFadeMode( fadeInDark );
      }
      else
      {
         m_boBacklight->setFadeMode( fadeIn );
      }
      // Should not be needed
      m_boBuzzer->getPwm()->setPwmValue(50);
   #endif
   //m_darkened = false;
}


void OApp::setPreviousScreen()
{
   if( m_pPreviousScreen != nullptr )
   {
      setCurrentScreen( m_pPreviousScreen );
   }
}


void OApp::event( const CTouch::SEvent touchEvent )
{
   Ocelli::SEvent event{touchEvent.x, touchEvent.y, (Ocelli::EEventType)touchEvent.type};
   #if defined (STM32)
   m_touchEventTimer=lrNow();

   if( m_darkened )
   {
      m_boBacklight->setFadeMode( fadeIn );
      m_darkened = false;
   }

   if( m_boBuzzer && (! m_boBuzzer->isActive() ) )
   {
      switch(event.type)
      {
         case Ocelli::EEventType::pressed:
            m_boBuzzer->setBeepMode( beepPressed );
            break;
         case Ocelli::EEventType::released:
            m_boBuzzer->setBeepMode( beepReleased );
            break;
         default:
            break;
      }
   }
  #endif
   OWidget *pCurrentWidget = nullptr;
   if( m_pNaviScreen && ( event.y > 320 -64) )
   {
      pCurrentWidget = m_pNaviScreen->findWidget( event.x, event.y );
   }
   else
   {
      if(m_pCurrentScreen)
      {
         pCurrentWidget = m_pCurrentScreen->findWidget( event.x, event.y );
      }
   }
   referEvent(pCurrentWidget, event);
}


void OApp::referEvent(OWidget *widget, Ocelli::SEvent &event)
{
   switch(event.type)
   {
      case Ocelli::EEventType::pressed:
      {
         if(m_pressedWidget)
         {
            lCritical("Pressed event when current widget still present");
         }
         m_pressedWidget=widget;
         if(widget)
         {
            widget->event(event);
         }
         break;
      }
      case Ocelli::EEventType::moved:
      {
         if( m_pressedWidget && ( m_pressedWidget == widget ) )
         {
            m_pressedWidget->event(event);
         }
         break;
      }
      case Ocelli::EEventType::released:
      {
         if( m_pressedWidget )
         {
            m_pressedWidget->event(event);
            if( m_pressedWidget == widget )
            {
               Ocelli::SEvent clickEvent=event;
               clickEvent.type = Ocelli::EEventType::clicked;
               m_pressedWidget->event( clickEvent );
            }
         }
         m_pressedWidget=nullptr;
         break;
      }
      case Ocelli::EEventType::clicked:
      {
         lWarning("Click-Events should not be send from touch");
         break;
      }
      default:
         break;
   }
}


void OApp::draw()
{
   if(m_pNaviScreen)
   {
      m_pNaviScreen->draw();
   }

   if(m_pCurrentScreen)
   {
      m_pCurrentScreen->draw();
   }
}


void OApp::eventLoop()
{
   #if defined (STM32)
   if(!m_darkened)
   {
      if( lrElapsedSeconds(m_touchEventTimer) >= 20 )
      {
          m_boBacklight->setFadeMode( slowFadeDark );
          m_darkened=true;
      }
   }
   else
   {
      if( lrElapsedSeconds( m_touchEventTimer ) >= 40 )
      {
         if(m_pStandbyScreen)
         {
            setCurrentScreen( m_pStandbyScreen );
         }
      }
   }
   #endif
   if(m_pCurrentScreen)
   {
      m_pCurrentScreen->eventLoop();
   }
}


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