/*
 *
 * Easy-to use interface to the ZYPP dependency resolver
 *
 * Author: Stefan Hundhammer <sh@suse.de>
 *
 **/

#ifndef ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H
#define ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H
#ifndef ZYPP_USE_RESOLVER_INTERNALS
#error Do not directly include this file!
#else

#include <list>
#include <string>

#include <zypp/base/ReferenceCounted.h>
#include <zypp/base/PtrTypes.h>

#include <zypp/PoolItem.h>

/////////////////////////////////////////////////////////////////////////
namespace zypp
{ ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
  namespace solver
  { /////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////
    namespace detail
    { ///////////////////////////////////////////////////////////////////

      class Resolver;

      DEFINE_PTR_TYPE(SolverQueueItem);

      DEFINE_PTR_TYPE(SolutionAction);
      typedef std::list<SolutionAction_Ptr> SolutionActionList;

        /**
         * Abstract base class for one action of a problem solution.
         **/
        class SolutionAction : public base::ReferenceCounted
        {
        protected:
            typedef Resolver ResolverInternal;
            SolutionAction ();
        public:
            virtual ~SolutionAction();

            // ---------------------------------- I/O
            virtual std::ostream & dumpOn( std::ostream & str ) const;
            friend std::ostream& operator<<(std::ostream & str, const SolutionAction & action)
                { return action.dumpOn (str); }
            friend std::ostream& operator<<(std::ostream & str, const SolutionActionList & actionlist);

            // ---------------------------------- methods
            /**
             * Execute this action.
             * Returns 'true' on success, 'false' on error.
             **/
            virtual bool execute (ResolverInternal & resolver) const = 0;

        public:
            /** The solution contains only 'do not install patch:' actions. */
            virtual bool skipsPatchesOnly() const;
        };


        /**
         * A problem solution action that performs a transaction
         * (installs, removes, keep ...)  one resolvable
         * (package, patch, pattern, product).
         **/
        typedef enum
        {
            KEEP,
            INSTALL,
            REMOVE,
            UNLOCK,
            LOCK,
            REMOVE_EXTRA_REQUIRE,
            REMOVE_EXTRA_CONFLICT,
            ADD_SOLVE_QUEUE_ITEM,
            REMOVE_SOLVE_QUEUE_ITEM,
        } TransactionKind;


        class TransactionSolutionAction: public SolutionAction
        {
        public:
            TransactionSolutionAction( PoolItem item,
                                       TransactionKind action )
                : SolutionAction(),
                  _item( item ), _action( action ) {}

            TransactionSolutionAction( Capability capability,
                                       TransactionKind action )
                : SolutionAction(),
                  _capability( capability ), _action( action ) {}


            TransactionSolutionAction( SolverQueueItem_Ptr item,
                                       TransactionKind action )
                : SolutionAction(),
                  _solverQueueItem( item ), _action( action ) {}

            TransactionSolutionAction( TransactionKind action )
                : SolutionAction(),
                  _item(), _action( action ) {}

          // ---------------------------------- I/O
          virtual std::ostream & dumpOn( std::ostream & str ) const;
          friend std::ostream& operator<<(std::ostream& str, const TransactionSolutionAction & action)
                { return action.dumpOn (str); }

          // ---------------------------------- accessors

          const PoolItem item() const { return _item; }
          const Capability capability() const { return _capability; }
          TransactionKind action() const { return _action; }

          // ---------------------------------- methods
          virtual bool execute(ResolverInternal & resolver) const;

        public:
            /** The solution contains only 'do not install patch:' actions. */
            bool skipsPatchesOnly() const override;

        protected:

            PoolItem _item;
            Capability _capability;
            SolverQueueItem_Ptr _solverQueueItem;

            const TransactionKind _action;
        };


        /**
         * Type of ignoring; currently only WEAK
         **/

        typedef enum
        {
            WEAK
        } InjectSolutionKind;


        /**
         * A problem solution action that injects an artificial "provides" to
         * the pool to satisfy open requirements or remove the conflict of
         * concerning resolvable
         *
         * This is typically used by "ignore" (user override) solutions.
         **/
        class InjectSolutionAction: public SolutionAction
        {
        public:

            InjectSolutionAction( PoolItem item,
                                  const InjectSolutionKind & kind)
                : SolutionAction(),
                  _item( item ),
                  _kind( kind ) {}

          // ---------------------------------- I/O
          virtual std::ostream & dumpOn( std::ostream & str ) const;
          friend std::ostream& operator<<(std::ostream& str, const InjectSolutionAction & action)
                { return action.dumpOn (str); }

          // ---------------------------------- accessors
            const PoolItem item() const { return _item; }

          // ---------------------------------- methods
            virtual bool execute(ResolverInternal & resolver) const;

        protected:
            PoolItem _item;
            const InjectSolutionKind _kind;
        };


      ///////////////////////////////////////////////////////////////////
    };// namespace detail
    /////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////
  };// namespace solver
  ///////////////////////////////////////////////////////////////////////
  ///////////////////////////////////////////////////////////////////////
};// namespace zypp
/////////////////////////////////////////////////////////////////////////
#endif // ZYPP_USE_RESOLVER_INTERNALS
#endif // ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H

