function decodeBigInt(x)
{
	x &= 0x1249249249249249n;
	x = (x | (x / 4n)) & 0x10c30c30c30c30c3n;
	x = (x | (x / 16n)) & 0x100f00f00f00f00fn;
	x = (x | (x / 256n)) & 0x1f0000ff0000ffn;
	x = (x | (x / 65536n)) & 0x1f00000000ffffn;
	x = (x | (x / 4294967296n)) & 0x1fffffn;
	return Number(x);
}

function maskIntArray(buffer,location, numberOfBytes, reverse){
		if(numberOfBytes<8){
			var value = 0;
			if(!reverse){
				for (var i = 0; i < numberOfBytes; i++) {
					value = (value * 256) + buffer[location+i];
				}
			}else{
				for (var i = numberOfBytes - 1; i >= 0; i--) {
					value = (value * 256) + buffer[location+i];
				}
			}

			return value;
		}else{
			var value = 0n;
			if(!reverse){
				for (var i = 0; i < numberOfBytes; i++) {
					value = (value * 256n) + BigInt(buffer[location+i]);
				}
			}else{
				for (var i = numberOfBytes - 1; i >= 0; i--) {
					value = (value * 256n) + BigInt(buffer[location+i]);
				}
			}

			return value;
		}
	}

function processZappchaData(event) {
	let numPoints = event.data.numPoints;
	let minx = event.data.minx;
	let miny = event.data.miny;
	let minz = event.data.minz;
	let maxx = event.data.maxx;
	let maxy = event.data.maxy;
	let maxz = event.data.maxz;
	let filter = event.data.filter;
	let bb = new Uint8ClampedArray(event.data.buffer);
	let version = event.data.version;
	
	let position = new Float32Array(numPoints * 3);
	let color = new Uint8Array(numPoints * 4);
	let intensities = new Float32Array(numPoints);
	let classifications = new Uint8Array(numPoints)
	let indices = new ArrayBuffer(numPoints * 4);
	let u32Indices = new Uint32Array(indices);
	
	if(version===18){
		numPoints = event.data.originalNumPoints;
		let before = 0n;
		let shift = 0n;
		let idx = 0n;
		let colour = 0;
		let i = 0;
		let byteRead = 0;
		
		let readPos = 0;
		let iterator = 0;
		let deleted = 0;
		
		while(iterator < numPoints){
			shift = 0n;
			byteRead = 0;
			idx = 0n;
			
			while (true) {
				byteRead = bb[readPos];
				readPos++;
				idx |= BigInt(byteRead & 0x7f) << shift;
				shift += 7n;
				if (!(byteRead & 0x80)) break;
			}
			
			idx += before;
			
			before = idx;
			
			colour = maskIntArray(bb,readPos,3,true);
			
			readPos+=3;
			
			//deleted = color & 0x01;
			
			//if (deleted===0){
			position[i * 3 + 0] = minx + decodeBigInt(idx) * filter;
			position[i * 3 + 1] = miny + decodeBigInt(idx / 2n) * filter;
			position[i * 3 + 2] = minz + decodeBigInt(idx / 4n) * filter;
			
			color[i * 4 + 2] = (colour & 0x1e) * 8; 
			color[i * 4 + 1] = (colour / 32 & 0x1f) * 8;
			color[i * 4 + 0] = (colour / 1024 & 0x1f) * 8;
			color[i * 4 + 3] = 255;

			intensities[i] = (colour / 32768 & 0x1f) * 8;
			classifications[i] = (colour / 1048576 & 0x0f);
			u32Indices[i] = i;
		
			i++;
			//}
			iterator++;
		}
	}else{
		let i=0;
		let pos = 0;
		let bytesPerVertex = event.data.bytesPerVertex;
		let bytesPerAxis = event.data.bytesPerAxis;
		while(i<numPoints){
			try{
				pos = (i*bytesPerVertex)+bytesPerAxis+bytesPerAxis+bytesPerAxis;
				
				position[i * 3 + 0] = maskIntArray(bb,(i*bytesPerVertex)+0,bytesPerAxis,false)/ 10000.0 + minx;
				position[i * 3 + 1] = maskIntArray(bb,(i*bytesPerVertex)+bytesPerAxis,bytesPerAxis,false)/ 10000.0 + miny;
				position[i * 3 + 2] = maskIntArray(bb,(i*bytesPerVertex)+bytesPerAxis+bytesPerAxis,bytesPerAxis,false)/ 10000.0 + minz;
				
				color[i * 4 + 0] = bb[pos];
				color[i * 4 + 1] = bb[pos+1];
				color[i * 4 + 2] = bb[pos+2];
				color[i * 4 + 3] = 255;

				intensities[i] = bb[pos+3];
				classifications[i] = bb[pos+4];
				u32Indices[i] = i;
			
			}catch(errpoint){
				console.log(bytesPerVertex);
				console.log(i);
				console.log(errpoint);
			}
			i++;
		}
	}
	
	let message = {
		position: position,
		color: color,
		intensities: intensities,
		classifications: classifications,
		indices: indices
	};
	
	bb = null;
	
	postMessage(message);

}

onmessage = processZappchaData;