// py_ex_raw.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <eter/py_tinker.h>

#include "raw.h"

template<typename Pixel>
class pyraw_const_iterator : public raw_const_iterator<Pixel>
{
public:
	typedef raw_const_iterator<Pixel> base_raw_iterator;

public:
	pyraw_const_iterator(Pixel* pixels, int pitch, int width, int height) : base_raw_iterator(pixels, pitch, width, height)
	{
	}
	virtual ~pyraw_const_iterator()
	{
	}
	Pixel getx()
	{
		Pixel ret;
		if (!base_raw_iterator::getx(ret))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			ret = 0;
		}
		return ret;
	}
	PyObject* gets(int len)
	{
		if (!base_raw_iterator::can_refs(len))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			return Py_BuildValue("s", "");
		}
		return PyString_FromStringAndSize((const char*)base_raw_iterator::quick_refs(len), sizeof(Pixel)*len);
	}
	PyObject* peeks(int len)
	{
		if (!base_raw_iterator::can_refs(len))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			return Py_BuildValue("s", "");
		}
		return PyString_FromStringAndSize((const char*)base_raw_iterator::quick_peeks(len), sizeof(Pixel)*len);
	}
	
};


template<typename Pixel>
class pyraw_iterator : public raw_iterator<Pixel>
{
public:
	typedef raw_iterator<Pixel> base_raw_iterator;

public:
	pyraw_iterator(Pixel* pixels, int pitch, int width, int height) : base_raw_iterator(pixels, pitch, width, height)
	{
	}
	Pixel getx()
	{
		Pixel ret;
		if (!base_raw_iterator::getx(ret))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			ret = 0;
		}
		return ret;
	}
	PyObject* gets(int len)
	{
		if (!base_raw_iterator::can_refs(len))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			return Py_BuildValue("s", "");
		}
		return PyString_FromStringAndSize((const char*)base_raw_iterator::quick_refs(len), sizeof(Pixel)*len);
	}
	PyObject* peeks(int len)
	{
		if (!base_raw_iterator::can_refs(len))
		{
			throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
			return Py_BuildValue("s", "");
		}
		return PyString_FromStringAndSize((const char*)base_raw_iterator::quick_peeks(len), sizeof(Pixel)*len);
	}
	
};

template<typename Pixel>
class pyraw : public raw<Pixel>
{
	public:
		typedef raw<Pixel> base_raw;
		typedef pyraw_iterator<Pixel> iterator;

	public:
		pyraw(int width, int height) : base_raw(width, height)
		{
		}
		Pixel getx(int x, int y)
		{
			Pixel ret;
			if (!base_raw::getx(x, y, ret))
			{
				throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
				ret = 0;
			}
			return ret;
		}
		PyObject* gets(int x, int y, int len)
		{
			if (!base_raw::can_refs(x, y, len))
			{
				throw PyTinkerException(PyExc_RuntimeError, "OUT_OF_RANGE");
				return Py_BuildValue("s", "");
			}
			return PyString_FromStringAndSize((const char*)base_raw::quick_refs(x, y, len), sizeof(Pixel)*len);
		}
		iterator* get_iterator()
		{
			return new iterator(m_pixels, m_width, m_width, m_height);
		}
};

//////////////////////////////////////////////////////////////////////

typedef unsigned char	pixel8;

typedef pyraw_const_iterator<pixel8> pyraw8_const_iterator;
typedef pyraw_iterator<pixel8> pyraw8_iterator;
typedef pyraw<pixel8> pyraw8;

py_tinker::class_<pyraw8_const_iterator> build_raw8_const_iterator()
{
	using namespace py_tinker;
	return class_<pyraw8_const_iterator>("raw8_const_iterator", construct4<pyraw8_const_iterator, pixel8*, int, int, int>())
		.deft("move", &pyraw8_const_iterator::move)
		.deft("next", &pyraw8_const_iterator::next)	
		.deft("find", &pyraw8_const_iterator::find)
		.deft("skip", &pyraw8_const_iterator::skip)
		.deft("ret_line", &pyraw8_const_iterator::ret_line)
		.defv("new_line", &pyraw8_const_iterator::new_line)
		.deft("next_line", &pyraw8_const_iterator::next_line)		
		.deft("getx", &pyraw8_const_iterator::getx)		
		.deft("gets", &pyraw8_const_iterator::gets)
		.deft("peeks", &pyraw8_const_iterator::peeks)
		;
}

py_tinker::class_<pyraw8_iterator> build_raw8_iterator()
{
	using namespace py_tinker;
	return class_<pyraw8_iterator>("raw8_iterator", construct4<pyraw8_iterator, pixel8*, int, int, int>())
		.deft("move", &pyraw8_iterator::move)
		.deft("next", &pyraw8_iterator::next)	
		.deft("find", &pyraw8_iterator::find)
		.deft("skip", &pyraw8_iterator::skip)
		.deft("ret_line", &pyraw8_iterator::ret_line)
		.defv("new_line", &pyraw8_iterator::new_line)
		.deft("next_line", &pyraw8_iterator::next_line)		
		.deft("getx", &pyraw8_iterator::getx)		
		.deft("gets", &pyraw8_iterator::gets)
		.deft("peeks", &pyraw8_iterator::peeks)
		.deft("putx", &pyraw8_iterator::putx)
		.deft("puts", &pyraw8_iterator::puts)
		.deft("fill", &pyraw8_iterator::fill)		
		;
}

py_tinker::class_<pyraw8> build_raw8()
{
	using namespace py_tinker;
	return class_<pyraw8>("raw8", construct2<pyraw8, int, int>())
		.defv("clear", &pyraw8::clear)
		.deft("fill", &pyraw8::fill)
		.deft("putx", &pyraw8::putx)
		.deft("getx", &pyraw8::getx)
		.deft("puts", &pyraw8::puts)
		.deft("gets", &pyraw8::gets)
		.deft("fill", &pyraw8::fill)
		.deft("get_iterator", &pyraw8::get_iterator)
		;
}

//////////////////////////////////////////////////////////////////////

typedef unsigned short	pixel16;

typedef pyraw_const_iterator<pixel16> pyraw16_const_iterator;
typedef pyraw_iterator<pixel16> pyraw16_iterator;
typedef pyraw<pixel16> pyraw16;

py_tinker::class_<pyraw16_const_iterator> build_raw16_const_iterator()
{
	using namespace py_tinker;
	return class_<pyraw16_const_iterator>("raw16_const_iterator", construct4<pyraw16_const_iterator, pixel16*, int, int, int>())
		.deft("move", &pyraw16_const_iterator::move)
		.deft("next", &pyraw16_const_iterator::next)	
		.deft("find", &pyraw16_const_iterator::find)
		.deft("skip", &pyraw16_const_iterator::skip)
		.deft("ret_line", &pyraw16_const_iterator::ret_line)
		.defv("new_line", &pyraw16_const_iterator::new_line)
		.deft("next_line", &pyraw16_const_iterator::next_line)		
		.deft("getx", &pyraw16_const_iterator::getx)		
		.deft("gets", &pyraw16_const_iterator::gets)
		.deft("peeks", &pyraw16_const_iterator::peeks)
		;
}

py_tinker::class_<pyraw16_iterator> build_raw16_iterator()
{
	using namespace py_tinker;
	return class_<pyraw16_iterator>("raw16_iterator", construct4<pyraw16_iterator, pixel16*, int, int, int>())
		.deft("move", &pyraw16_iterator::move)
		.deft("next", &pyraw16_iterator::next)	
		.deft("find", &pyraw16_iterator::find)
		.deft("skip", &pyraw16_iterator::skip)
		.deft("ret_line", &pyraw16_iterator::ret_line)
		.defv("new_line", &pyraw16_iterator::new_line)
		.deft("next_line", &pyraw16_iterator::next_line)		
		.deft("getx", &pyraw16_iterator::getx)		
		.deft("gets", &pyraw16_iterator::gets)
		.deft("peeks", &pyraw16_iterator::peeks)
		.deft("putx", &pyraw16_iterator::putx)
		.deft("puts", &pyraw16_iterator::puts)
		.deft("fill", &pyraw16_iterator::fill)		
		;
}

py_tinker::class_<pyraw16> build_raw16()
{
	using namespace py_tinker;
	return class_<pyraw16>("raw16", construct2<pyraw16, int, int>())
		.defv("clear", &pyraw16::clear)
		.deft("fill", &pyraw16::fill)
		.deft("putx", &pyraw16::putx)
		.deft("getx", &pyraw16::getx)
		.deft("puts", &pyraw16::puts)
		.deft("gets", &pyraw16::gets)
		.deft("fill", &pyraw16::fill)
		.deft("get_iterator", &pyraw16::get_iterator)
		;
}

//////////////////////////////////////////////////////////////////////

typedef unsigned long	pixel32;

typedef pyraw_const_iterator<pixel32> pyraw32_const_iterator;
typedef pyraw_iterator<pixel32> pyraw32_iterator;
typedef pyraw<pixel32> pyraw32;

py_tinker::class_<pyraw32_const_iterator> build_raw32_const_iterator()
{
	using namespace py_tinker;
	return class_<pyraw32_const_iterator>("raw32_const_iterator", construct4<pyraw32_const_iterator, pixel32*, int, int, int>())
		.deft("move", &pyraw32_const_iterator::move)
		.deft("next", &pyraw32_const_iterator::next)	
		.deft("find", &pyraw32_const_iterator::find)
		.deft("skip", &pyraw32_const_iterator::skip)
		.deft("ret_line", &pyraw32_const_iterator::ret_line)
		.defv("new_line", &pyraw32_const_iterator::new_line)
		.deft("next_line", &pyraw32_const_iterator::next_line)		
		.deft("getx", &pyraw32_const_iterator::getx)		
		.deft("gets", &pyraw32_const_iterator::gets)
		.deft("peeks", &pyraw32_const_iterator::peeks)
		;
}

py_tinker::class_<pyraw32_iterator> build_raw32_iterator()
{
	using namespace py_tinker;
	return class_<pyraw32_iterator>("raw32_iterator", construct4<pyraw32_iterator, pixel32*, int, int, int>())
		.deft("move", &pyraw32_iterator::move)
		.deft("next", &pyraw32_iterator::next)	
		.deft("find", &pyraw32_iterator::find)
		.deft("skip", &pyraw32_iterator::skip)
		.deft("ret_line", &pyraw32_iterator::ret_line)
		.defv("new_line", &pyraw32_iterator::new_line)
		.deft("next_line", &pyraw32_iterator::next_line)		
		.deft("getx", &pyraw32_iterator::getx)		
		.deft("gets", &pyraw32_iterator::gets)
		.deft("peeks", &pyraw32_iterator::peeks)
		.deft("putx", &pyraw32_iterator::putx)
		.deft("puts", &pyraw32_iterator::puts)
		.deft("fill", &pyraw32_iterator::fill)		
		;
}

py_tinker::class_<pyraw32> build_raw32()
{
	using namespace py_tinker;
	return class_<pyraw32>("raw32", construct2<pyraw32, int, int>())
		.defv("clear", &pyraw32::clear)
		.deft("fill", &pyraw32::fill)
		.deft("putx", &pyraw32::putx)
		.deft("getx", &pyraw32::getx)
		.deft("puts", &pyraw32::puts)
		.deft("gets", &pyraw32::gets)
		.deft("fill", &pyraw32::fill)
		.deft("get_iterator", &pyraw32::get_iterator)
		;
}

PyMODINIT_FUNC
initraw()
{
	py_tinker::module_("raw")
		.def(build_raw8())
		.def(build_raw8_iterator())		
		.def(build_raw8_const_iterator())		
		.def(build_raw16())
		.def(build_raw16_iterator())
		.def(build_raw16_const_iterator())
		.def(build_raw32())
		.def(build_raw32_iterator())
		.def(build_raw32_const_iterator())
		;
}

impl_arg_class_(pyraw32_const_iterator)
impl_arg_class_(pyraw32_iterator)
impl_arg_class_(pyraw32)
impl_arg_class_(pyraw16_const_iterator)
impl_arg_class_(pyraw16_iterator)
impl_arg_class_(pyraw16)
impl_arg_class_(pyraw8_const_iterator)
impl_arg_class_(pyraw8_iterator)
impl_arg_class_(pyraw8)



int main(int argc, char* argv[])
{
	Py_Initialize();
	Py_SetProgramName((char*)"py_test");
			
	initraw();
	py_tinker::PyEmbed_RunMainFile("ex_raw.py");
	Py_Finalize();	

	return 0;
}
