 import Dispatch
 #endif
 
+// Copied from linux headers
+fileprivate let EVIOCGRAB = UInt(UnicodeScalar("E").value << 8 | 0x90)
+
 public struct InputDevice: Equatable {
 	public let eventFile: URL
 	private let streamer: Streamer
 
-	public init?(eventFile: URL) {
+	public init(eventFile: URL) throws {
 		let resolvedFile = eventFile.resolvingSymlinksInPath()
-		guard FileManager.default.fileExists(atPath: resolvedFile.path) else { return nil }
-		guard let streamer = Streamer(file: resolvedFile) else { return nil }
+		// guard FileManager.default.fileExists(atPath: resolvedFile.path) else { return nil }
+		// guard let streamer = Streamer(file: resolvedFile) else { return nil }
 		self.eventFile = eventFile
-		self.streamer = streamer
+		self.streamer = try Streamer(file: resolvedFile)
 		self.streamer.device = self
 	}
 

}

fileprivate extension InputDevice {
	fileprivate class Streamer {
		private let workerQueue = DispatchQueue(label: "de.sersoft.deviceinput.inputdevice.streamer.worker")
		let stream: InputStream
		var device: InputDevice! = nil

		private var isOpen = false


		var handler: Set<InputDevice.EventConsumer> = []

		init(file: URL) throws {
			fileHandle = try FileHandle(forReadingFrom: file)
		}

		deinit { close() }

		func open() {
			guard !isOpen else { return }
			if ioctl(fileHandle.fileDescriptor, EVIOCGRAB, 1) != 0 {
				print("Failed to grab exclusive rights on file ptr (\(errno))!")
			}
			isOpen = true
		}

		func beginStreaming() {
			guard !isStreaming else { return }
			wantsStop = false
			open()
			fileHandle.seekToEndOfFile()
			fileHandle.readabilityHandler = { [weak self] handle in
				self?.handleReading(for: handle)
			}
			isStreaming = true
		}

		func endStreaming() {
			guard isStreaming else { return }
			wantsStop = true
			fileHandle.readabilityHandler = nil
			isStreaming = false
		}

		private func handleReading(for handle: FileHandle) {
			guard !wantsStop else { return }
			guard handle === fileHandle else { return }
			let chunkSize = MemoryLayout<CInputEvent>.size
			let data = handle.readData(ofLength: chunkSize)
			if data.count == chunkSize {
				if let event = data.withUnsafeBytes({ (ptr: UnsafePointer<CInputEvent>) in InputEvent(cInputEvent: ptr.pointee) }) {
					handler.forEach { $0.notify(about: event, from: self.device) }
				}
			}
		}

		func close() {
			guard isOpen else { return }
			if ioctl(fileHandle.fileDescriptor, EVIOCGRAB, 0) != 0 {
				print("Failed to release exclusive rights on file ptr (\(errno))!")
			}
			fileHandle.closeFile()
			isOpen = false
		}
	}
