#ifndef PINMUX_VARIANT_HPP
#define PINMUX_VARIANT_HPP
//----------------------------------------------------------------------------
///
/// \file   variant.hpp
///
/// \brief  class to check if variant lists are matching
///
/// \date   20220625
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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


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

#undef DEBUG_VARIANT
#include <QString>
#include <QStringList>
#include <QDebug>

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


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


/**
 * @brief   Check if variant descriptions matches
 *
 *          Each periphery of an application can describe its variant-condition
 *          as strings, e.g. "debug,uart".
 *          When application is build, the target variaton can be defined.
 *          e.g. when building the variant "!debug", each periphery is
 *          included except periphery marked with "debug".
 */
class CVariant
{
private:
   QStringList m_inclusive;
   QStringList m_exclusive;

public:
   CVariant(  )
   {}
   CVariant( const QString& str )
   {
      set(str);
   }
   void set( const QString& str )
   {
      m_inclusive=str.split(",");
      m_exclusive=m_inclusive;
      for(auto i = m_inclusive.begin(); i!=m_inclusive.end();)
      {
         if( (*i).isEmpty() || ( (*i)[0] == '!' ) )
         {
            i=m_inclusive.erase(i);
         }
         else
         {
            ++i;
         }
      }
      for(auto i = m_exclusive.begin(); i!=m_exclusive.end();)
      {
         if( (*i).isEmpty() || ( (*i)[0] != '!' ) )
         {
            i=m_exclusive.erase(i);
         }
         else
         {
            (*i).remove(0,1);
            ++i;
         }
      }
   }

   bool matches(const QString& str) const
   {
      CVariant ref(str);
      return(matches( ref ));
   }

   bool matches(const CVariant& ref) const
   {
      bool m=false;

      #if defined DEBUG_VARIANT
      qWarning() << "---------";
      qWarning() << "Inclusive variants: " << m_inclusive << "/" << m_inclusive.size();
      qWarning() << "Exclusive variants: " << m_exclusive << "/" << m_exclusive.size();
      qWarning() << "Inclusive reference: " << ref.m_inclusive << "/" << ref.m_inclusive.size();
      qWarning() << "Exclusive reference: " << ref.m_exclusive << "/" << ref.m_exclusive.size();
      #endif

      if( m_inclusive.empty() )
      {
         m=true;
      }
      else
      {
         for(auto i = m_inclusive.begin(); i!=m_inclusive.end();i++)
         {
            if( ref.m_inclusive.contains(*i) )
            {
               #if defined DEBUG_VARIANT
                  qWarning() << "   match because reference contrians " << *i;
               #endif
               m=true;
            }
         }
      }

      for(auto i = m_exclusive.begin(); i!=m_exclusive.end();i++)
      {
         if( ref.m_inclusive.contains(*i) )
         {
            m=false;
         }
      }

      for(auto i = ref.m_exclusive.begin(); i!=ref.m_exclusive.end();i++)
      {
         if( m_inclusive.contains(*i) )
         {
            m=false;
         }
      }

      return( m );
   }
};


//---fin----------------------------------------------------------------------
#endif // ? ! PINMUX_VARIANT_HPP
