#ifndef _INSERT_QUERY_HPP_
#define _INSERT_QUERY_HPP_

#include <mysql++/mysql++.h>
#include <string>

struct insert_query
{
	typedef std::list< std::pair<std::string, std::string> > values_type;

	struct field_def
	{
		field_def(insert_query& q, const std::string& name)
			: query_(q), name_(name)
		{
		}

		template <typename T>
		field_def& operator=(const T& value)
		{
			query_.set(name_, value);
			return *this;
		}

	private:
		insert_query& query_;
		std::string name_;
	};

	insert_query(const std::string& table_name)
		: table_(table_name)
	{
	}

	field_def operator[](const std::string& name)
	{
		return field_def(*this, name);
	}

	template <typename T>
	void set(const std::string& name, const T& value)
	{
		std::ostringstream os;
		os << mysqlpp::quote << value;
		std::cerr << name << ": " << os.str();
		values_.push_back(std::make_pair(name, os.str()));
	}

	std::string query() const
	{
		values_type::const_iterator i;
		std::ostringstream os;
		os << "INSERT INTO " << table_
		   << "(";
		i = values_.begin();
		if (i != values_.end())
			os << i->first;
		++i;
		while (i != values_.end())
		{
			os << ", " << i->first;
			++i;
		}
		os << ") "
		   << "VALUES (";
		i = values_.begin();
		if (i != values_.end())
			os << i->second;
		++i;
		while (i != values_.end())
		{
			os << ", " << i->second;
			++i;
		}
		os << ")";

		return os.str();
	}

	unsigned int execute(mysqlpp::Connection& conn)
	{
		mysqlpp::Query q = conn.query();
		q << query();
		q.execute();
		return q.insert_id();
	}

private:
	std::string table_;
	values_type values_;
};

#endif // _INSERT_QUERY_HPP_
