// src/backend/dynamic_sub_request.hh - Copyright 2005, 2006, University
//               of Padova, dept. of Pure and Applied
//               Mathematics
//
// This file is part of SGPEMv2.
//
// This is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// SGPEMv2 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with SGPEMv2. If not, see http://www.gnu.org/licenses/.


#ifndef DYNAMIC_SUB_REQUEST_HH
#define DYNAMIC_SUB_REQUEST_HH 1

namespace sgpem
{
  class DynamicSubRequest;
  class SerializeVisitor;
  class Resource;
  class StaticSubRequest;
}

#include "dynamic_request.hh"
#include "dynamic_resource.hh"
#include "static_sub_request.hh"

#include <sgpemv2/request.hh>
#include <sgpemv2/sub_request.hh>

#include <memory>

namespace sgpem
{
  /** \brief Represents the dynamic status of a subrequest
   */
  class SG_DLLLOCAL DynamicSubRequest : public SubRequest
  {
  public:
    /** \brief Constructor
     *
     * Only ::History knows how to use this :-).
     */
    DynamicSubRequest(StaticSubRequest* core, DynamicRequest* owner);

    /** \brief "Special" copy constructor, which copies everything except owner
     * \param owner The owner of the new DynamicSubRequest
     */
    DynamicSubRequest(const DynamicSubRequest& other, DynamicRequest* owner);

    virtual ~DynamicSubRequest();

    /** \brief Tells if this object equals another of the same type
     *
     * \return true If they own a reference to the same Static object
     * \return false Otherwise
     */
    virtual bool operator==(const SubRequest& op2) const;

    /** \brief Returns the key to the DynamicResource that was requested
     *
     * The correct ::Resource object can be obtained via
     * Environment.get_resources(), using the returned value as a key
     */
    resource_key_t get_resource_key() const;

    /** \brief Returns the time the resource is needed
     *
     * This time is meant relative to a process executed time.
     */
    unsigned int get_length() const;

    int get_queue_position() const;
    void set_queue_position(int position);

    virtual DynamicRequest& get_request();

    state get_state() const;
    state set_state(state new_state);

    unsigned int get_remaining_time() const;

    /** \brief Decreases remaining time by 1
     */
    unsigned int decrease_remaining_time();

    void serialize(SerializeVisitor& translator) const;

    StaticSubRequest& get_core();
    const StaticSubRequest& get_core() const;

  private:
    // Undefined
    DynamicSubRequest(const DynamicSubRequest&);

    std::shared_ptr<StaticSubRequest> _static_subrequest;
    DynamicRequest*  _owner;
    int              _queue_position;
    unsigned int     _ran_for;
    state            _state;
  };

}

#endif
