Files
Xaibatsu-Control-Panel/XIONControlPanel/Servers/ServerMultiplex.swift

111 lines
3.1 KiB
Swift
Raw Normal View History

//
// ServerMultiplex.swift
// XIONControlPanel
//
// Created by James Magahern on 3/14/20.
// Copyright © 2020 XION. All rights reserved.
//
import Foundation
protocol ServerMultiplexDelegate
{
func serverMultiplex(_ multiplex: ServerMultiplex, didAddDevices devices: [AnyDevice])
func serverMultiplex(_ multiplex: ServerMultiplex, devicesStateChanged devices: [AnyDevice])
func serverMultiplex(_ multiplex: ServerMultiplex, didEncounterError error: Error)
}
enum ServerMultiplexError : Error
{
case UnknownDevice
}
class ServerMultiplex
{
public var delegate: ServerMultiplexDelegate?
public private(set) var devices = Set<AnyDevice>()
private var servers: [Server] = []
public var numServers: Int { get { return servers.count } }
public func addServer(_ server: Server)
{
servers.append(server)
}
public func numberOfConnectedServers() -> Int
{
return servers.filter { $0.connected == true }.count
}
public func toggleDeviceState(_ device: AnyDevice, state: DeviceState, completion: @escaping (Error?) -> Void)
{
if let server = (servers.first { $0.responsibleForDevice(device) }) {
server.toggleDevice(device, state: state, completion: completion)
// Update internal state
if let index = devices.firstIndex(of: device) {
devices[index].state = state
}
} else {
completion(ServerMultiplexError.UnknownDevice)
}
}
public func refreshDevices()
{
self.servers.forEach { (server: Server) in
server.fetchDevices { (result: Result<[AnyDevice], Error>) in
self.handleServerFetchResult(result)
}
}
}
}
extension ServerMultiplex
{
private func handleServerFetchResult(_ result: Result<[AnyDevice], Error>)
{
switch result {
case .success(let devices):
handleDevicesChanged(devices)
case .failure(let error):
handleError(error)
}
}
private func handleDevicesChanged(_ devicesChanged: [AnyDevice])
{
let newDevicesSet = Set<AnyDevice>(devicesChanged)
let additions = newDevicesSet.subtracting(self.devices)
let changed = newDevicesSet.filter { (device: AnyDevice) in
if let existing = (devices.first { $0.hashValue == device.hashValue }) {
return existing.state != device.state
}
return false
}
self.devices = self.devices.union(newDevicesSet)
if additions.count > 0 {
DispatchQueue.main.async {
self.delegate?.serverMultiplex(self, didAddDevices: Array(additions))
}
}
if changed.count > 0 {
DispatchQueue.main.async {
self.delegate?.serverMultiplex(self, devicesStateChanged: Array(changed))
}
}
}
private func handleError(_ error: Error)
{
DispatchQueue.main.async {
self.delegate?.serverMultiplex(self, didEncounterError: error)
}
}
}