/**
  @file
  @author Stefan Frings
*/

#ifndef HTTPSESSION_H
#define HTTPSESSION_H

#include <QByteArray>
#include <QVariant>
#include <QReadWriteLock>
#include "httpglobal.h"

namespace stefanfrings {

/**
  This class stores data for a single HTTP session.
  A session can store any number of key/value pairs. This class uses implicit
  sharing for read and write access. This class is thread safe.
  @see HttpSessionStore should be used to create and get instances of this class.
*/

class DECLSPEC HttpSession {

public:

    /**
      Constructor.
      @param canStore The session can store data, if this parameter is true.
      Otherwise all calls to set() and remove() do not have any effect.
     */
    HttpSession(const bool canStore=false);

    /**
      Copy constructor. Creates another HttpSession object that shares the
      data of the other object.
    */
    HttpSession(const HttpSession& other);

    /**
      Copy operator. Detaches from the current shared data and attaches to
      the data of the other object.
    */
    HttpSession& operator= (const HttpSession& other);

    /**
      Destructor. Detaches from the shared data.
    */
    virtual ~HttpSession();

    /** Get the unique ID of this session. This method is thread safe. */
    QByteArray getId() const;

    /**
      Null sessions cannot store data. All calls to set() and remove() 
      do not have any effect. This method is thread safe.
    */
    bool isNull() const;

    /** Set a value. This method is thread safe. */
    void set(const QByteArray& key, const QVariant& value);

    /** Remove a value. This method is thread safe. */
    void remove(const QByteArray& key);

    /** Get a value. This method is thread safe. */
    QVariant get(const QByteArray& key) const;

    /** Check if a key exists. This method is thread safe. */
    bool contains(const QByteArray& key) const;

    /**
      Get a copy of all data stored in this session.
      Changes to the session do not affect the copy and vice versa.
      This method is thread safe.
    */
    QMap<QByteArray,QVariant> getAll() const;

    /**
      Get the timestamp of last access. That is the time when the last
      HttpSessionStore::getSession() has been called.
      This method is thread safe.
    */
    qint64 getLastAccess() const;

    /**
      Set the timestamp of last access, to renew the timeout period.
      Called by  HttpSessionStore::getSession().
      This method is thread safe.
    */
    void setLastAccess();

private:

    struct HttpSessionData {

        /** Unique ID */
        QByteArray id;

        /** Timestamp of last access, set by the HttpSessionStore */
        qint64 lastAccess;

        /** Reference counter */
        int refCount;

        /** Used to synchronize threads */
        QReadWriteLock lock;

        /** Storage for the key/value pairs; */
        QMap<QByteArray,QVariant> values;

    };

    /** Pointer to the shared data. */
    HttpSessionData* dataPtr;

};

} // end of namespace

#endif // HTTPSESSION_H
