#ifndef ARENA_PINMUX_PERIPHERY_TRIVIA_H
#define ARENA_PINMUX_PERIPHERY_TRIVIA_H
//----------------------------------------------------------------------------
///
/// \file   peripheryTrivia.h
///
/// \brief  See implementation for further details
///
/// \date   20180129
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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


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

#include <QString>
#include <QList>
#include <QMap>
#include <QRandomGenerator>
#include <QObject>
#include <QJsonObject>
#include <QVariant>
#include <jsonObject.h>


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

class CPeriphery;

enum class ERelation
{
   unknown,
   normal,
   unshared=normal,
   shared,
   exclusive,
   placeholder,
   fabricate,
};

enum class EMatchMode
{
   undefined = 0,
   predefined = 1,
   alternateFunction = 2,
   peripheryName = 3,
   peripheryType = 4,
};


/** \brief  Trivial description of an periphery or reference
 *  
 *          The trivia has no links to references or real peripheries.
 *          Both CReference and CPeriphery inherit from CPeripheryTrivia
 */
class CPeripheryTrivia: public CJsonObject
{
private:
   QString m_name;
   QString m_peripheryType;
   QString m_peripheryName;
   bool m_pruneName=false;
   //QMap<QString, QString> m_attributes;
   static int idCounter;
   int m_id;
   ERelation m_relation;
   bool m_filtered = false;

public:
   CPeripheryTrivia(const QString &name, const  QString &peripheryType
                    , const  QString &peripheryName
                    , const  QString &relation={} )
      :m_name(name)
      ,m_peripheryType(peripheryType)
      ,m_peripheryName(peripheryName)
      ,m_relation(ERelation::normal)
   {
      if( m_name.size() && ( m_name[0] == '^' ) )
      {
         m_pruneName = true;
         m_name.remove('^');
      }
      m_id=idCounter++;
      setRelation(relation);
   }
   void updateId()
   {
      m_id=idCounter++;
   }
   virtual ~CPeripheryTrivia()
   {
   }
   const QString &getName() const
   {
      return(m_name);
   }
   const QString &getPeripheryType() const
   {
      return(m_peripheryType);
   }
   bool matchesType(const QString &type) const;
   const QString &setName(const QString &name)
   {
      return(m_name=name);
   }
   const ERelation &getRelation() const
   {
      return(m_relation);
   }
   void setRelation(ERelation relation)
   {
      m_relation=relation;
   }

   void setRelation(const QString &mode)
   {
      m_relation=ERelation::normal;

      if( (mode == "normal") || (mode == "-") )
      {
      }
      else if(mode == "shared")
      {
         m_relation=ERelation::shared;
      }
      else if(mode == "placeholder")
      {
         m_relation=ERelation::placeholder;
      }
      else if(mode == "exclusive")
      {
         m_relation=ERelation::exclusive;
      }
      else if(mode == "fabricate")
      {
         m_relation=ERelation::fabricate;
      }
      else if(mode.isEmpty())
      {
         m_relation=ERelation::normal;
      }
      else
      {
         qFatal( "unknown shared mode: %s", qPrintable(mode));
      }
   }
   int getId() const
   {
      return(m_id);
   }
   const QString &setPeripheryName(const QString &peripheryName)
   {
      return(m_peripheryName=peripheryName);
   }
   const QString &getPeripheryName() const
   {
      return(m_peripheryName);
   }
   QString getPeripheryNameForCode() const
   {
      QString peripheryName=m_peripheryName;
      peripheryName.replace(".", "_");
      peripheryName.replace(" ", "_");
      return(peripheryName);
   }
   virtual void dump() const;

   ERelation getShared() const
   {
      return( m_relation );
   }
   bool isForcedExclusive() const
   {
      return( m_relation == ERelation::exclusive );
   }
   bool doPruneName() const
   {
      return( m_pruneName );
   }

   /** \brief  The physical periphery block of the periphery as string
    *
    *          Only usable for GPIOs; eg "A", "B", ... "F"
    */
   QString getPeripheryBlock() const;

   /** \brief the physical number of the periphery as string
    *  
    *         E.g. for UART2 the number string is 2.
    *         When it can not find a number it defaults to "1".
    */
   QString getPeripheryNumber( ) const;
   
   bool isFiltered()
   {
      return( m_filtered );
   }
   
   void filterOut()
   {
      m_filtered = true;
   }
};


//---fin----------------------------------------------------------------------
#endif // ? ! ARENA_PINMUX_PERIPHERY_TRIVIA_H
