/*---------------------------------------------------------------------\
|                          ____ _   __ __ ___                          |
|                         |__  / \ / / . \ . \                         |
|                           / / \ V /|  _/  _/                         |
|                          / /__ | | | | | |                           |
|                         /_____||_| |_| |_|                           |
|                                                                      |
\---------------------------------------------------------------------*/
/** \file	zypp/sat/Queue.h
 */
#ifndef ZYPP_SAT_QUEUE_H
#define ZYPP_SAT_QUEUE_H

#include <iosfwd>

#include <zypp/Globals.h>
#include <zypp/base/PtrTypes.h>
#include <zypp/sat/detail/PoolMember.h>

///////////////////////////////////////////////////////////////////
namespace zypp
{
  ///////////////////////////////////////////////////////////////////
  namespace sat
  {
    class Queue;
    using SolvableQueue = Queue;	///< Queue with Solvable ids
    using StringQueue = Queue;		///< Queue with String ids

    ///////////////////////////////////////////////////////////////////
    /// \class Queue
    /// \brief Libsolv Id queue wrapper.
    /// \todo template value_type to work with IString and other Id based types
    ///////////////////////////////////////////////////////////////////
    class ZYPP_API Queue
    {
      public:
        using size_type = unsigned int;
        using value_type = detail::IdType;
        using const_iterator = const value_type *;

      public:
        /** Default ctor: empty Queue. */
        Queue();

        /** Dtor */
        ~Queue();

        bool empty() const;
        size_type size() const;
        const_iterator begin() const;
        const_iterator end() const;

        /** Return iterator to the 1st occurance of \a val_r or \ref end. */
        const_iterator find( value_type val_r ) const;

        /** Return whether the Queue contais at lest one element with value \a val_r. */
        bool contains( value_type val_r ) const
        { return( find( val_r ) != end() ); }

        /** Return the 1st Id in the queue or \c 0 if empty. */
        value_type first() const;

        /** Return the last Id in the queue or \c 0 if empty. */
        value_type last() const;

        /** Return the Id at \a idx_r in the queue
         * \throws std::out_of_range if \a idx_r is out of range
         */
        const value_type & at( size_type idx_r ) const;

        /** Return the Id at \a idx_r in the queue
         * \throws std::out_of_range if \a idx_r is out of range
         */
        value_type & at( size_type idx_r );

        /** Return the Id at \a idx_r in the queue (no range check) */
        const value_type & operator[]( size_type idx_r ) const;

        /** Return the Id at \a idx_r in the queue (no range check) */
        value_type & operator[]( size_type idx_r );

        /** Clear the queue. */
        void clear();

        /** Remove all occurances of \a val_r from the queue. */
        void remove( value_type val_r );

        /** Push a value to the end off the Queue. */
        void push( value_type val_r );
        /** \overload */
        void push_back( value_type val_r )
        { push( val_r ); }

        /** Push a value if it's not yet in the Queue. */
        void pushUnique( value_type val_r );

        /** Pop and return the last Id from the queue or \c 0 if empty. */
        value_type pop();
        /** \overload */
        value_type pop_back()
        { return pop(); }

        /** Push a value to the beginning off the Queue. */
        void push_front( value_type val_r );

        /** Pop and return the 1st Id from the queue or \c 0 if empty. */
        value_type pop_front();

     public:
        operator detail::CQueue *();			///< libsolv backdoor
        operator const detail::CQueue *() const		///< libsolv backdoor
        { return _pimpl.get(); }
      private:
        RWCOW_pointer<detail::CQueue> _pimpl;		///< Pointer to implementation
    };

    /** \relates Queue Stream output */
    std::ostream & operator<<( std::ostream & str, const Queue & obj ) ZYPP_API;

    /** \relates Queue Stream output assuming a Solvable queue. */
    std::ostream & dumpOn( std::ostream & str, const Queue & obj ) ZYPP_API;

    /** \relates Queue */
    bool operator==( const Queue & lhs, const Queue & rhs ) ZYPP_API;

    /** \relates Queue */
    inline bool operator!=( const Queue & lhs, const Queue & rhs )
    { return !( lhs == rhs ); }

  } // namespace sat
  ///////////////////////////////////////////////////////////////////

  /** \relates Queue Clone function for RWCOW_pointer */
  template<> sat::detail::CQueue * rwcowClone<sat::detail::CQueue>( const sat::detail::CQueue * rhs );

} // namespace zypp
///////////////////////////////////////////////////////////////////
#endif // ZYPP_SAT_QUEUE_H
