#include <iostream>
#include <string>
#include "simplesock.h"

// A very simple HTTP request class
class HttpRequest
{
    // Let's declare the <<() operator as friend so it can access the private vars
    friend std::ostream& operator<<(std::ostream& lhs, const HttpRequest& rhs);

    private:
        std::string     _host;
        unsigned short  _port;
        std::string     _path;

    public:
        HttpRequest(const char *host, unsigned short port, const char *path = "/")
            : _host(host),
              _port(port),
              _path(path)
        {
        }
};

// You can extend the formatted output operations like this:
std::ostream& operator<<(std::ostream& lhs, const HttpRequest& rhs)
{
    // Let's write the http request
    lhs << "GET " << rhs._path << " HTTP/1.1\r\n"
        << "Host: " << rhs._host << "\r\n"
        << "Connection: Close\r\n"
        << "\r\n";

    // Then return back the calling stream
    return lhs;
}

int main(int argc, char *argv[])
{
    const char *host = "www.google.com";
    unsigned short port = 80;

    try
    {
        // Connect to google
        simplesock::sockstream http(host, port);

        // Ensure that we're connected
        if (http.is_open())
        {
            // Construct HttpRequest object
            HttpRequest request(host, port);

            // Let's write our request, this calls our custom overloaded <<()
            http << request;
            // simplesock::sockstream is buffered, let's flush the packet
            http.flush();

            // Receive response and print it, std::getline() returns EOF when everything has been read
            for (std::string line; std::getline(http, line);)
            {
                std::cout << line.substr(0, line.size()-1) << std::endl;
            }
        }
        else
        {
            std::cout << "Unable to connect to " << host << " on port " << port << std::endl;
        }
    }
    catch (simplesock::init_fail ex)
    {
        std::cout << ex.what() << std::endl;
    }

    return 0;
}
