// Local configuration
#include "config.h"

// Implementation
#include "URL.hpp"

namespace UI {
namespace Util {
namespace Http {

URL::URL(std::string const & url)
	:url_(url)
{
	if (url.substr(0, 7) != "http://")
	{
		UI_THROW("Invalid http url syntax: " + url);
	}
	std::string::size_type pathPos(url.find_first_of("/?:", 7));

	host_ = url.substr(7, pathPos == std::string::npos ? pathPos : pathPos-7);

	port_ = 80;
	if (pathPos != std::string::npos && url[pathPos] == ':')
	{
		std::string::size_type newPathPos(url.find_first_of("/?", pathPos+1));
		port_ = ato<int>(url.substr(pathPos+1, newPathPos == std::string::npos ? newPathPos : newPathPos-pathPos-1));
		port_ = port_ == 0 ? 80 : port_;
		pathPos = newPathPos;
	}
	path_ = pathPos == std::string::npos || url[pathPos] != '/' ? "/" : "";
	path_ += pathPos == std::string::npos ? "" : url.substr(pathPos);
}

URL & URL::addParam(std::string const & key, std::string const & value)
{
	char const sep(path_.find_first_of('?') == std::string::npos ? '?' : '&');
	path_ += sep + key + "=" + value;
	return *this;
}

std::string  const & URL::getHost() const { return host_; }
unsigned int const & URL::getPort() const { return port_; }
std::string  const & URL::getPath() const { return path_; }
std::string  const   URL::getURL()  const { return "http://" + host_ + (port_ == 80 ? "" : ":" + UI::Util::tos(port_)) + path_; }


URLGet::URLGet(std::string const & url, long int const & timeout)
	:url_(url)
{
	Connection c(url_.getHost(), url_.getPort(), timeout, 0, timeout, 0, false);

	c.write(RequestLine(RequestLine::Get_, url_.getPath()));
	c.write(Header().add("Host", url_.getHost()));
	c.writeLine();
	c.s().flush();

	status_ = c.readLine();
	header_ = c.readHeader();
	if (header_.exists("Content-Length"))
	{
		body_ = c.readBlock(header_.get<std::streamsize>("Content-Length"));
	}
}

URL         const & URLGet::getURL()    const { return url_; }
StatusLine  const & URLGet::getStatus() const { return status_; }
Header      const & URLGet::getHeader() const { return header_; }
std::string const & URLGet::getBody()   const { return body_; }

}}}
