/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_EVENT_HPP
#define NMM_EVENT_HPP NMM_EVENT_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/comm/serialize/SerializedValue.hpp"
#include "nmm/comm/serialize/SequenceValue.hpp"
#include "nmm/comm/serialize/TValue.hpp"
#include "nmm/comm/serialize/SerializedException.hpp"

#include "visibility.hpp"

namespace NMM {
  
  class Value;
  class CEvent;
  
  /** An event represents an atomic function call.
   */
  class DLLEXPORT Event : public SerializedValue {
  public:
    /** Default-Constructor
     *
     * @param key event key
     */
    Event(const std::string& key = "");

    /** Creates an Event with given number of values.
     *
     * @param key event key
     * @param arg_size size of internal argument array
     */
    Event(const std::string& key, unsigned int arg_size);

    /** Creates an Event with three Values
     *
     * @param key event key
     * @param value1 value argument 1
     * @param value2 value argument 2
     * @param value3 value argument 3
     * @param value4 value argument 4
     * @param value5 value argument 5
     * @param value6 value argument 6
     * @param value7 value argument 7
     */
    Event(const std::string& key, Value* value1, Value* value2 = 0, Value* value3 = 0, Value* value4 = 0, Value* value5 = 0, Value* value6 = 0, Value* value7 = 0);

    /** Copy constructor.
     *
     * @param event to copy
     */
    Event(const Event& event);

    /** Destructor.
     */
    virtual ~Event();

    /** Assignement operator. 
     * 
     * The values stored inside the event desides if a deep copy is done
     * or not.
     * 
     * @param e Event to copy values from
     * @return reference to this object
     */
    const Event&  operator=(const Event& e);

    /** Set a value at specified position.
     *  If position bigger than internal array, the value is not set.
     *
     * @param position array index to set value
     * @param value value to set
     */
    void setValue(unsigned int position, Value* value);

    /** Assign a new key to this Event.
     *
     * @param k new event key
     */
    inline void setKey(const std::string& k)                   { key.setValue(k); }

    /** Returns the event key.
     *
     * @return reference to event key
     */
    inline const std::string& getKey()                   const { return key.getRValue(); }

    /** Returns the size of internal value array.
     *
     * @return size of internal value array
     */
    inline size_t getArgSize()                           const { return arg_array.size(); }

    /** Returns the value at specified position. 
     * Returns NULL if this value is not set or position is bigger than internal array size.
     *
     * @param position array index of requested value
     * @return pointer to requested value
     */
    const Value*  getValue(unsigned int position)   const ;

    /** Returns the value at specified position. 
     * Returns NULL if this value is not set or position is bigger than internal array size.
     *
     * @param position  array index of requested value
     * @return pointer to requested value
     */
    Value*  getValue(unsigned int position) ;

    /** Sets the return value. 
     * The memory management is done by the event.
     *
     * @param value return value to set
     */
    inline  void setReturnValue(Value* value)             { __arg_return[0] = value; }

    /** Returns the return value of an executed method.
     * 
     * This method returns the return value of an executed method. The memoty management
     * of the returned value is done by the event. If the caller needs a copy of the value
     * he can use the copy() method.
     *
     * @return return value of executed method
     */
    inline       Value* getReturnValue()                  { return __arg_return[0]; }

    /** Returns the return value of an executed method.
     * 
     * This method returns the return value of an executed method. The memoty management
     * of the returned value is done by the event. If the caller needs a copy of the value
     * he can use the copy() method.
     *
     * @return return value of executed method
     */
    inline const Value* getReturnValue()            const { return __arg_return[0]; }

    /** Returns a copy of this event.
     * 
     * @return copy of this event
     */
    virtual Event* copy()                           const { return new Event(*this);}

    /** Resizes the internal value array to store more values.
     *
     * @param size new size of internal value array
     */
    inline void resize(unsigned int size)                 { arg_array.resize(size); }

    /** Release all values.
     */
    void erase();

    /** Returns an exception which was thrown during the execution of the event.
     *
     * @return Exception which was thrown during the execution of the event.
     */
    inline       SerializedException* getException()       { return __exception.getValue(); }

    /** Returns an exception which was thrown during the execution of the event.
     *
     * @return Exception which was thrown during the execution of the event.
     */
    inline const SerializedException* getException() const { return __exception.getValue(); }

    /** Sets the exception which was thrown threw the executed method.
     *
     * @param exception SerializedException which was thrown threw the executed method.
     */
    void  setException(const SerializedException& exception);

    /** Disable certain memory types. 
     * 
     * This mehtod is interesting for complex  data structures to disable certain Memory types 
     * like In or Out-Values for (de-)serialization. 
     *
     * @param type memory type to disable
     */
    virtual void disableMemoryType(Value::MemoryMgm type);

    /** Resets the state of internal datastructure wich was disabled before to earlier state.
     */
    virtual void resetMemoryType();

    static const std::string type_name;                      ///< stores the typename of the event
  
  
  private:
    
    /** Register attributes for serialization/deserialization.
     */
    void assign();

    TValue<std::string> key;                                 ///< stores the event key                
    SequenceValue<> arg_array;                               ///< stores the arguments of the event

    SequenceValue<>       __arg_return;                      ///< stores the return value
    TOutValue<SerializedException*> __exception;             ///< stores the return value
    std::vector<Value*>        __internal_arg_vector;        ///< stores the disabled argments of the event
    std::vector<Value*>        __internal_return_vector;     ///< stores the disabled return value.
  };
  
}

#include "nmm/nmm_suffix.hpp"

#endif
