import argparse
import keyboard
import logging
import mouse
import pickle
import threading
import time

LOGGER = logging.getLogger("playback")

def main() -> None:
	parser = argparse.ArgumentParser()
	parser.add_argument(
		"-d", "--delay",
		default=5,
		type=int,
		help="Seconds to wait before replay."
	)
	parser.add_argument(
		"-i", "--input",
		default="dump.capture",
		help="Name of the file to replay from."
	)
	parser.add_argument(
		"--verbose",
		action="store_true",
		help="Show verbose messages."
	)
	args = parser.parse_args()
	logging.basicConfig(
		level = logging.DEBUG if args.verbose else logging.INFO
	)
	_do_delay(args.delay)

	events = _load_events(args.input)
	_play_events(events)

def _play_events(events) -> None:
	LOGGER.info("Playback started.")
	key_state = keyboard.stash_state()
	last_time = None
	for event in events:
		if last_time is not None:
			to_sleep = event.time - last_time
			if to_sleep > 0:
				time.sleep(to_sleep)
		last_time = event.time
		if isinstance(event, keyboard.KeyboardEvent):
			_play_event_keyboard(event)
		elif any([
				isinstance(event, mouse.ButtonEvent),
				isinstance(event, mouse.MoveEvent),
				isinstance(event, mouse.WheelEvent),
			]):
			_play_event_mouse(event)
		else:
			raise ValueError(f"Not a recognized event {event}")
			
	keyboard.restore_modifiers(key_state)
	LOGGER.info("Done.")

def _play_event_keyboard(event) -> None:
	LOGGER.debug("Key %s", event)
	key = event.scan_code or event.name
	keyboard.press(key) if event.event_type == keyboard.KEY_DOWN else keyboard.release(key)

def _play_event_mouse(event) -> None:
	LOGGER.debug("Mouse %s", event)
	if isinstance(event, mouse.ButtonEvent):
		if event.event_type == mouse.UP:
			mouse.release(event.button)
		else:
			mouse.press(event.button)
	elif isinstance(event, mouse.MoveEvent):
		mouse.move(event.x, event.y, absolute=True)
	elif isinstance(event, mouse.WheelEvent):
		mouse.wheel(event.delta)
	
def _do_delay(delay: int) -> None:
	if not delay:
		return
	print("\n")
	for i in range(delay):
		print(f"\rStarting in {delay-i} seconds")
		time.sleep(1)

def _load_events(filename: str):
	with open(filename, "rb") as input_:
		events = pickle.load(input_)
	LOGGER.debug("Loaded %s", filename)
	return events


if __name__ == "__main__":
	main()