#include <iostream>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrim_Cylinder.hxx>
#include <BRepTools.hxx>
#include "topology/ShapeAlgorithms.h"
#include "easylogging++/easylogging++.h"
#include "config.h"

using namespace std;

INITIALIZE_EASYLOGGINGPP

bool testHaveEqualShapes_Box_Origin() {
	// Construct 2 huge boxes with slightly different size <4%, and positioned at origin.
	gp_Pnt boxPnt_11(0.1, 0.1, 0.1);
	gp_Pnt boxPnt_12(100000, 200000, 300000);
	BRepPrimAPI_MakeBox substrateBox_1(boxPnt_11, boxPnt_12);
	substrateBox_1.Build();
	TopoDS_Shape box_1 = substrateBox_1.Shape();

	gp_Pnt boxPnt_21(0, 0, 0);
	gp_Pnt boxPnt_22(100000.1, 200000.1, 300000.1);
	BRepPrimAPI_MakeBox substrateBox_2(boxPnt_21, boxPnt_22);
	substrateBox_2.Build();
	TopoDS_Shape box_2 = substrateBox_2.Shape();

	if (!ShapeAlgorithms::have_equal_shapes(box_1, box_2)) {
		cout << "Boxes 1 and 2 should be considered equal, but they are not:\n";
		BRepTools::Dump(box_1, cout);
		BRepTools::Dump(box_2, cout);
		return false;
	}
	if (!ShapeAlgorithms::have_equal_shapes(box_2, box_1)) {
		cout << "Boxes 1 and 2 should be considered equal, but they are not:\n";
		BRepTools::Dump(box_2, cout);
		BRepTools::Dump(box_1, cout);
		return false;
	}
	return true;
}

bool testHaveEqualShapes_Sphere_Cylinder_Origin() {
	// Construct 2 huge boxes with slightly different size <4%, and positioned at origin.
	gp_Pnt origin(0, 0, 0);
	BRepPrimAPI_MakeSphere makeSphere(origin, pow(1.0 / (M_PI * 4.0 / 3), 1.0 / 3));
	makeSphere.Build();
	TopoDS_Shape sphere = makeSphere.Shape();

	gp_Pnt box_1(-0.5, -0.5, -0.5);
	gp_Pnt box_2(0.5, 0.5, 0.5);
	BRepPrimAPI_MakeBox makeBox(box_1, box_2);
	makeBox.Build();
	TopoDS_Shape box = makeBox.Shape();

	if (ShapeAlgorithms::have_equal_shapes(sphere, box)) {
		cout << "Shapes should be considered distinct, but they are not:\n";
		BRepTools::Dump(sphere, cout);
		BRepTools::Dump(box, cout);
		return false;
	}
	if (ShapeAlgorithms::have_equal_shapes(box, sphere)) {
		cout << "Shapes should be considered distinct, but they are not:\n";
		BRepTools::Dump(box, cout);
		BRepTools::Dump(sphere, cout);
		return false;
	}
	return true;
}

bool testHaveEqualShapes_Face() {
	BRep_Builder b;
	BRep_Builder b2;

	TopoDS_Shape face1;
	BRepTools::Read(face1, (std::string(TEST_DIR) + "/topology/assets/shaft_small_face_1.brep").c_str(), b);
	
	TopoDS_Shape face2;
	BRepTools::Read(face2, (std::string(TEST_DIR) + "/topology/assets/shaft_small_face_2.brep").c_str(), b2);

	if (!ShapeAlgorithms::have_equal_shapes(face1, face2)) {
		cout << "Shapes should be considered equal, but they are not:\n";
		BRepTools::Dump(face1, cout);
		BRepTools::Dump(face2, cout);
		return false;
	}
	if (!ShapeAlgorithms::have_equal_shapes(face2, face1)) {
		cout << "Shapes should be considered equal, but they are not:\n";
		BRepTools::Dump(face1, cout);
		BRepTools::Dump(face2, cout);
		return false;
	}
	return true;
}


int main() {
	bool res = true;
	
	res &= testHaveEqualShapes_Box_Origin();
	res &= testHaveEqualShapes_Sphere_Cylinder_Origin();
	res &= testHaveEqualShapes_Face();

	return res ? 0 : 1;
}
