import libcamera as libcam
import paho.mqtt.client as mqtt
import selectors
import sys
import time
import io
from PIL import Image

import mfb

image_count = 9999

def camera_name(camera):
	return camera.id

def handle_camera_event(cm):
	reqs = cm.get_ready_requests()
	for req in reqs:
		process_request(req)

def sendImage(plane):
	image = Image.frombytes("RGBA", (800, 600), plane.tobytes())
	pngBytes = io.BytesIO()
	image.save(pngBytes, "png")
	mqttc.publish("spider/telemetry/camfeed", pngBytes.getvalue())

def process_request(request):
	global camera, image_count
	global mqttc

	image_count += 1
	if image_count > 1:
		image_count = 0
		print(f'Request completed: {request}')

		requestMetadata = request.metadata
		for id, value in requestMetadata.items():
			print(f'\t{id.name} = {value}')

		buffers = request.buffers
		for _, buffer in buffers.items():
			metadata = buffer.metadata

			print(f' seq: {metadata.sequence:06} timestamp: {metadata.timestamp} bytesused: ' +
				'/'.join([str(p.bytes_used) for p in metadata.planes]))
			with mfb.MappedFrameBuffer(buffer) as mappedBuffer:
				for plane in mappedBuffer.planes:
					sendImage(plane)

	request.reuse()
	camera.queue_request(request)

def main():
	global camera
	global mqttc

	mqttc = mqtt.Client()
	mqttc.connect("mqtt.seeseepuff.be", 1883, 60)
	mqttc.loop_start()

	cm = libcam.CameraManager.singleton()

	for camera in cm.cameras:
		print(f' - {camera_name(camera)}')

	if not cm.cameras:
		print("No cameras were detected")
		return -1

	camera_id = cm.cameras[0].id
	camera = cm.get(camera_id)
	camera.acquire()

	config = camera.generate_configuration([libcam.StreamRole.Viewfinder])

	stream_config = config.at(0)
	print(f'Default viewfinder configuration is: {stream_config}')

	config.validate()
	print(f'Validated viewfinder configuration is: {stream_config}')

	camera.configure(config)

	allocator = libcam.FrameBufferAllocator(camera)

	for cfg in config:
		allocated = allocator.allocate(cfg.stream)
		print(f'Allocated {allocated} buffers for stream')

	stream = stream_config.stream
	buffers = allocator.buffers(stream)
	requests = []
	for i in range(len(buffers)):
		request = camera.create_request()

		buffer = buffers[i]
		request.add_buffer(stream, buffer)

		request.set_control(libcam.controls.Brightness, 0.5)

		requests.append(request)

	camera.start()
	for request in requests:
		camera.queue_request(request)

	sel = selectors.DefaultSelector()
	sel.register(cm.event_fd, selectors.EVENT_READ, lambda fd: handle_camera_event(cm))

	start_time = time.time()

	while True:
		events = sel.select()
		for key, mask in events:
			key.data(key.fileobj)

	camera.stop()
	camera.release()
	mqttc.disconnect()
	mqttc.loop_stop()

sys.exit(main())