/*
 * File: urlstream.h
 * ----------------------
 * This file exports the <code>iurlstream</code> class, which
 * implements an input stream for reading data from URLs.
 */

#ifndef _urlstream_h
#define _urlstream_h

#include <iostream>
#include <sstream>
#include <string>

/*
http://www.cplusplus.com/doc/tutorial/files/

When we operate with file streams, these are associated to an internal buffer object of type streambuf.
This buffer object may represent a memory block that acts as an intermediary between the stream and the physical file.
For example, with an ofstream, each time the member function put (which writes a single character) is called, the character may be inserted in this intermediate buffer instead of being written directly to the physical file with which the stream is associated.

The operating system may also define other layers of buffering for reading and writing to files.

When the buffer is flushed, all the data contained in it is written to the physical medium (if it is an output stream).
This process is called synchronization and takes place under any of the following circumstances:
 - When the file is closed: before closing a file, all buffers that have not yet been flushed are synchronized and all pending data is written or read to the physical medium.
 - When the buffer is full: Buffers have a certain size. When the buffer is full it is automatically synchronized.
 - Explicitly, with manipulators: When certain manipulators are used on streams, an explicit synchronization takes place. These manipulators are: flush and endl.
 - Explicitly, with member function sync(): Calling the stream's member function sync() causes an immediate synchronization. This function returns an int value equal to -1 if the stream has no associated buffer or in case of failure. Otherwise (if the stream buffer was successfully synchronized) it returns 0.
*/
class iurlstream : public std::istream {
    /*
     * Constructor: iurlstream
     * Usage: iurlstream stream;
     * -----------------------
     * Initializes a new iurlstream that is not attached to any source.
     */
    iurlstream();

    /*
     * Constructor: iurlstream
     * Usage: iurlstream stream("http://www.google.com/");
     * -----------------------
     * Initializes a new iurlstream that is attached to the given source URL.
     */
    iurlstream(std::string url);

    /*
     * Closes the currently-opened URL connection, if it is open.
     * If the stream is not open, puts the stream into a fail state.
     */
    void close();

    /*
     * Returns the most recent HTTP error code received, if any.
     * Returns 0 if no error codes have been issued.
     */
    int getErrorCode() const;

    /*
     * Returns whether or not this stream is connected to a URL for reading.
     */
    bool is_open();

    /*
     * Opens the given URL for reading.
     */
    void open(std::string url = "");

private:
    std::string m_url;
    std::stringbuf m_buf;
    int m_lastError;
};

/* return type */
typedef enum {
    /* Client side errors */
    ERRHOST=-1, /* No such host */
    ERRSOCK=-2, /* Can't create socket */
    ERRCONN=-3, /* Can't connect to host */
    ERRWRHD=-4, /* Write error on socket while writing header */
    ERRWRDT=-5, /* Write error on socket while writing data */
    ERRRDHD=-6, /* Read error on socket while reading result */
    ERRPAHD=-7, /* Invalid answer from data server */
    ERRNULL=-8, /* Null data pointer */
    ERRNOLG=-9, /* No/Bad length in header */
    ERRMEM=-10, /* Can't allocate memory */
    ERRRDDT=-11,/* Read error while reading data */
    ERRURLH=-12,/* Invalid url - must start with 'http://' */
    ERRURLP=-13,/* Invalid port in url */


    /* Return code by the server */
    ERR400=400, /* Invalid query */
    ERR403=403, /* Forbidden */
    ERR408=408, /* Request timeout */
    ERR500=500, /* Server error */
    ERR501=501, /* Not implemented */
    ERR503=503, /* Service overloaded */

    /* Succesful results */
    OK0 = 0,   /* successfull parse */
    OK201=201, /* Ressource succesfully created */
    OK200=200  /* Ressource succesfully read */

} http_retcode;

#endif // _urlstream_h
