

function createPointcloudData(pointcloud) {

	let material = pointcloud.material;

	let ranges = [];
	
	for(let [name, value] of material.ranges){
		ranges.push({
			name: name,
			value: value,
		});
	}

	if(typeof material.elevationRange[0] === "number"){
		ranges.push({
			name: "elevationRange",
			value: material.elevationRange,
		});
	}
	if(typeof material.intensityRange[0] === "number"){
		ranges.push({
			name: "intensityRange",
			value: material.intensityRange,
		});
	}

	let pointSizeTypeName = Object.entries(Potree.PointSizeType).find(e => e[1] === material.pointSizeType)[0];

	let jsonMaterial = {
		activeAttributeName: material.activeAttributeName,
		ranges: ranges,
		size: material.size,
		minSize: material.minSize,
		pointSizeType: pointSizeTypeName,
		matcap: material.matcap,
	};

	const pcdata = {
		name: pointcloud.name,
		url: pointcloud.pcoGeometry.url,
		position: pointcloud.position.toArray(),
		rotation: pointcloud.rotation.toArray(),
		scale: pointcloud.scale.toArray(),
		material: jsonMaterial,
	};

	return pcdata;
}

function createProfileData(profile){
	const data = {
		uuid: profile.uuid,
		name: profile.name,
		points: profile.points.map(p => p.toArray()),
		height: profile.height,
		width: profile.width,
	};

	return data;
}

function createVolumeData(volume){
	const data = {
		uuid: volume.uuid,
		type: volume.constructor.name,
		name: volume.name,
		position: volume.position.toArray(),
		rotation: volume.rotation.toArray(),
		scale: volume.scale.toArray(),
		visible: volume.visible,
		clip: volume.clip,
	};

	return data;
}

function createCameraAnimationData(animation){

	const controlPoints = animation.controlPoints.map( cp => {
		const cpdata = {
			position: cp.position.toArray(),
			target: cp.target.toArray(),
		};

		return cpdata;
	});

	const data = {
		uuid: animation.uuid,
		name: animation.name,
		duration: animation.duration,
		t: animation.t,
		curveType: animation.curveType,
		visible: animation.visible,
		controlPoints: controlPoints,
	};

	return data;
}

function createMeasurementData(measurement){

	const data = {
		uuid: measurement.uuid,
		name: measurement.name,
		points: measurement.points.map(p => p.position.toArray()),
		showDistances: measurement.showDistances,
		showCoordinates: measurement.showCoordinates,
		showArea: measurement.showArea,
		closed: measurement.closed,
		showAngles: measurement.showAngles,
		showHeight: measurement.showHeight,
		showCircle: measurement.showCircle,
		showAzimuth: measurement.showAzimuth,
		showEdges: measurement.showEdges,
		color: measurement.color.toArray(),
	};

	return data;
}

function createOrientedImagesData(images){
	const data = {
		cameraParamsPath: images.cameraParamsPath,
		imageParamsPath: images.imageParamsPath,
	};

	return data;
}

function createGeopackageData(geopackage){
	const data = {
		path: geopackage.path,
	};

	return data;
}

function createAnnotationData(annotation){

	const data = {
		uuid: annotation.uuid,
		title: annotation.title.toString(),
		description: annotation.description,
		position: annotation.position.toArray(),
		offset: annotation.offset.toArray(),
		children: [],
	};

	if(annotation.cameraPosition){
		data.cameraPosition = annotation.cameraPosition.toArray();
	}

	if(annotation.cameraTarget){
		data.cameraTarget = annotation.cameraTarget.toArray();
	}

	if(typeof annotation.radius !== "undefined"){
		data.radius = annotation.radius;
	}

	return data;
}

function createAnnotationsData(viewer){
	
	const map = new Map();

	viewer.scene.annotations.traverseDescendants(a => {
		const aData = createAnnotationData(a);

		map.set(a, aData);
	});

	for(const [annotation, data] of map){
		for(const child of annotation.children){
			const childData = map.get(child);
			data.children.push(childData);
		}
	}

	const annotations = viewer.scene.annotations.children.map(a => map.get(a));

	return annotations;
}

function createSettingsData(viewer){
	return {
		pointBudget: viewer.getPointBudget(),
		fov: viewer.getFOV(),
		edlEnabled: viewer.getEDLEnabled(),
		edlRadius: viewer.getEDLRadius(),
		edlStrength: viewer.getEDLStrength(),
		background: viewer.getBackground(),
		minNodeSize: viewer.getMinNodeSize(),
		showBoundingBoxes: viewer.getShowBoundingBox(),
	};
}

function createSceneContentData(viewer){

	const data = [];

	const potreeObjects = [];

	viewer.scene.scene.traverse(node => {
		if(node.potree){
			potreeObjects.push(node);
		}
	});

	for(const object of potreeObjects){
		
		if(object.potree.file){
			const saveObject = {
				file: object.potree.file,
			};

			data.push(saveObject);
		}


	}


	return data;
}

function createViewData(viewer){
	const view = viewer.scene.view;

	const data = {
		position: view.position.toArray(),
		target: view.getPivot().toArray(),
	};

	return data;
}

function createClassificationData(viewer){
	const classifications = viewer.classifications;

	const data = classifications;

	return data;
}

export function saveProject(viewer) {

	const scene = viewer.scene;

	const data = {
		type: "Potree",
		version: 1.7,
		settings: createSettingsData(viewer),
		view: createViewData(viewer),
		classification: createClassificationData(viewer),
		pointclouds: scene.pointclouds.map(createPointcloudData),
		measurements: scene.measurements.map(createMeasurementData),
		volumes: scene.volumes.map(createVolumeData),
		cameraAnimations: scene.cameraAnimations.map(createCameraAnimationData),
		profiles: scene.profiles.map(createProfileData),
		annotations: createAnnotationsData(viewer),
		orientedImages: scene.orientedImages.map(createOrientedImagesData),
		geopackages: scene.geopackages.map(createGeopackageData),
		// objects: createSceneContentData(viewer),
	};

	return data;
}
