#if ! defined LIBOCELLI_POINT
#define LIBOCELLI_POINT
//----------------------------------------------------------------------------
///
/// \file   point.hpp
///
/// \brief  class for coordinates
///
/// \date   20220619
/// \author Maximilian Seesslen <mes@seesslen.net>
///
//----------------------------------------------------------------------------


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


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


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

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


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


enum ECoordinateType
{
   absolut,
   //relative,
   sizes,
   center,
   diameter
};

struct OPoint
{
   //friend class OWidget;

public:

   int x;
   int y;

protected:
   //int m_x;
   //int m_y;
   ECoordinateType m_eCoordinateType = absolut;

public:

   constexpr OPoint()
      :x(-1)
      ,y(-1)
   {

   }
   constexpr OPoint(int _x, int _y, ECoordinateType eCoordinateType = absolut)
      :x(_x)
      ,y(_y)
      ,m_eCoordinateType ( eCoordinateType )
   {

   }
   static constexpr OPoint absolut1(const OPoint p1, const OPoint p2)
   {
      return ( ( p1.m_eCoordinateType == absolut ) ?
            p1
         : ( ( p1.m_eCoordinateType == center ) && ( p2.m_eCoordinateType == sizes ) ) ?
            OPoint( p1.x - ( ( p2.x - 1 ) / 2 ), p1.y - ( ( p2.y - 1 ) / 2 ) )
         : OPoint() );
   }
   static constexpr OPoint absolut2(const OPoint p1, const OPoint p2)
   {
      return( ( p2.m_eCoordinateType == absolut ) ?
            p2
         : ( ( p1.m_eCoordinateType == absolut ) && ( p2.m_eCoordinateType == sizes ) ) ? 
            OPoint( p1.x + p2.x - 1, p1.y + p2.y - 1 )
         : ( ( p1.m_eCoordinateType == center ) && ( p2.m_eCoordinateType == sizes ) ) ?
            OPoint( p1.x + ( ( p2.x - 1 ) / 2 ), p1.y + ( ( p2.y - 1 ) / 2 ) )
         : OPoint() );
   }
   void operator +=(const OPoint other)
   {
      x+=other.x;
      y+=other.y;
   }
};


class ORect
{
   private:
      const OPoint m_p1;
      const OPoint m_p2;

   public:
      constexpr ORect( const OPoint p1, const OPoint p2)
         :m_p1( OPoint::absolut1( p1, p2 ) )
         ,m_p2( OPoint::absolut2( p1, p2 ) )
      {
      }
      constexpr ORect(int x1, int y1, int x2, int y2)
         :m_p1( x1, y1 )
         ,m_p2( x2, y2 )
      {
      }
      int width() const
      {
         return( m_p2.x - m_p1.x + 1);
      }
      int height() const
      {
         return( m_p2.y - m_p1.y + 1);
      }
      int x1() const
      {
         return(m_p1.x);
      }
      int x2() const
      {
         return(m_p2.x);
      }
      int y1() const
      {
         return(m_p1.y);
      }
      int y2() const
      {
         return(m_p2.y);
      }
};


//---fin-----------------------------------------------------------------------
#endif // ? ! LIBOCELLI_POINT
