#include "stdafx.h"
#include "FormPyScript.h"

#include <iostream>
using namespace std;

#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>
#include <boost/ref.hpp>

#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

namespace bpy = boost::python;
using namespace boost;
using namespace boost::python;

#include "View3D.h"
#include "View2D.h"



typedef std::vector< lm::vec3f > VertAry;
typedef std::vector< lib_geo::VertAdj > VertAdjAry;
typedef std::vector< lib_geo::BaseFace > FaceAry;




BOOST_PYTHON_MODULE(CppExport)
{
	bpy::class_<lm::vec3f, boost::noncopyable>("vec3f")
		.def_readwrite("x", &lm::vec3f::x)
		.def_readwrite("y", &lm::vec3f::y)
		.def_readwrite("z", &lm::vec3f::z)
		;

	bpy::class_<lib_geo::VertAdj, boost::noncopyable>("VertAdj")
		;
	
	bpy::class_<lib_geo::BaseFace, boost::noncopyable>("BaseFace")
		;

	bpy::class_<lib_geo::BasePolyline, boost::noncopyable>("BasePolyline")
		;

	bpy::class_<VertAry, boost::noncopyable>("VertAry")
		//.def(vector_indexing_suite<VertAry>() )
		;

	bpy::class_<VertAdjAry, boost::noncopyable>("VertAdjAry")
		.def("size", &VertAdjAry::size)
		//.def("at", &VertAdjAry::at)
		;

	bpy::class_<FaceAry, boost::noncopyable>("FaceAry")
		.def("size", &FaceAry::size)
		//.def("at", &FaceAry::at)
		;

	bpy::class_<lib_geo::BaseMesh, boost::noncopyable>("BaseMesh")
		.def_readwrite("m_Verts", &lib_geo::BaseMesh::m_Verts)
		.def_readwrite("m_Normals", &lib_geo::BaseMesh::m_Normals)
		.def_readwrite("m_Faces", &lib_geo::BaseMesh::m_Faces)
		.def_readwrite("m_Polylines", &lib_geo::BaseMesh::m_Polylines)
		;

	bpy::class_<GeomObject, boost::noncopyable>("GeomObject")
		.def("SetVertSelect", &GeomObject::SetVertSelect)
		.def("GetVertSelect", &GeomObject::GetVertSelect)
		.def_readwrite("m_Mesh", &GeomObject::m_Mesh)
		;

	bpy::class_<View3D, boost::noncopyable>("View3D")
		.def("RepaintParent", &View3D::RepaintParent)
		;

	bpy::class_<View2D, boost::noncopyable>("View2D")
		.def("RepaintParent", &View2D::RepaintParent)
		;
}


FormPyScript::FormPyScript(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	ResetToDefaultScript();
}

FormPyScript::~FormPyScript()
{
}


void FormPyScript::on_actionRun_triggered()
{
	if( PyImport_AppendInittab( "CppExport" , initCppExport ) == -1 )
	{
		cout << "Failed" << endl;
		getchar();
		return;
	}

	Py_Initialize();

	PyObject* sys = PyImport_ImportModule("sys");
	PyObject* pystdout = PyFile_FromString("CONOUT$", "wt");
	if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout))
	{
		cout << "error to assign python stdout to console" << endl;
	}
	Py_DECREF(sys);
	Py_DECREF(pystdout);

	try
	{
		// CppExport以下をPythonにインポート
		bpy::object global_ns = bpy::import("__main__").attr("__dict__");
		bpy::exec
		(
			"from CppExport import *\n"
			, global_ns , global_ns
		);

		GeomObject* obj = m_Scene->GetPrimaryObject();

		// C++のオブジェクトへの参照をPythonに登録
		// この処理を実行する前に, Python内でSampleClassのインポートを行う必要有.
		global_ns["obj"] = boost::ref(obj);
		global_ns["view3d"] = boost::ref(m_View3d);
		global_ns["view2d"] = boost::ref(m_View2d);

		QString script = ui.plainTextEdit->document()->toPlainText();

		bpy::exec(script.toLocal8Bit().data(), global_ns, global_ns);
	}
	catch(const bpy::error_already_set&)
	{
		PyErr_Print();
	}

	Py_Finalize();
}

void FormPyScript::on_actionConsole_triggered()
{
	::AllocConsole();
	freopen( "CON", "r", stdin  );
	freopen( "CON", "w", stdout );
}

void FormPyScript::ResetToDefaultScript(void)
{
	QString s;
	s += "def pdir(obj):\n";
	s += "	print(dir(obj))\n";
	s += "\n";
	s += "def pdirl(obj):\n";
	s += "	for s in dir(obj):\n";
	s += "		print(s)\n";
	s += "\n";
	s += "\n";
	s += "print(\"--\")\n";
	s += "\n";
	s += "mesh = obj.m_Mesh\n";
	s += "\n";
	s += "view3d.RepaintParent()\n";
	ui.plainTextEdit->document()->setPlainText(s);
}

void FormPyScript::on_actionReset_triggered()
{
	ResetToDefaultScript();
}
