#include "socket_stream.h"
#include <cstdio>
#include <iostream>

template <typename Trait>
class tcp_device_wrapper : public device_wrapper<Trait> {
	typedef typename device_wrapper<Trait>::char_type char_type;

  private:
	tcp_socket mysock;
	bool abortme;

  public:
	tcp_device_wrapper() : abortme(false) {}
	tcp_device_wrapper(tcp_socket& s) : mysock(s), abortme(false) {}

	int read(char_type* buf, std::streamsize len) {
		if (abortme)
			return 0;
		return mysock.recv((void *)buf, len*sizeof(char_type));
	}

	int write(const char_type* buf, std::streamsize len) {
		if (abortme)
			return len;
		return mysock.send((const void*)buf, len*sizeof(char_type));
	}

	bool sync() {
		return true;
	}

	streamsize showmanyc() {
		return mysock.fionread()/sizeof(char_type);
	}

	void abort() {
		abortme = true;
		mysock.abort();
	}

	void clear_abort() {
		abortme = false;
	}

	// Uses default implementation of "seekoff"
	// Uses default implementation of "seekpos"
};

template <typename Trait>
void basic_tcpstreambuf<Trait>::abort()
{
	(dynamic_cast<tcp_device_wrapper<Trait>*>(this->dw))->abort();
}

template <typename Trait>
void basic_tcpstreambuf<Trait>::clear_abort()
{
	(dynamic_cast<tcp_device_wrapper<Trait>*>(this->dw))->clear_abort();
}

template <typename Trait>
basic_tcpstreambuf<Trait>::basic_tcpstreambuf()
: streambuf_impl<Trait, dual_buffer<typename Trait::char_type> >(new tcp_device_wrapper<Trait>)
{
}

template <typename Trait>
basic_tcpstreambuf<Trait>::basic_tcpstreambuf(tcp_socket& s)
	: streambuf_impl<Trait, dual_buffer<typename Trait::char_type> >(new tcp_device_wrapper<Trait>(s))
{
}



template <typename BS>
basic_tcpstream<BS>::basic_tcpstream()
	: BS(0)
{
	init(&tcpbuf);
}

template <typename BS>
basic_tcpstream<BS>::basic_tcpstream(tcp_socket& s)
	: BS(0),
	  tcpbuf(s)
{
	init(&tcpbuf);
}


// TODO: The following instantiations should be put in different library files

// Instatiate the interesting classes
template class basic_tcpstream< std::istream >;	// itcpstream
template class basic_tcpstream< std::ostream >;	// otcpstream
template class basic_tcpstream< std::iostream >;	// tcpstream

