import Cocoa
-private enum DockState: Int {
+protocol KenzoDockStatusObserver: class {
- case empty = 0
- case hasShip = 2
- case completed = 3
- case notOpen = -1
+ func didUpdate(state: KenzoDockStatus)
+}
+
+protocol KenzoDockStatusObserverDelegate: class {
+
+ func didChangeState(dock: KenzoDock)
+}
+
+final class KenzoDockObserver {
+
+ private let dock: KenzoDock
+ private var observation: NSKeyValueObservation?
+
+ weak var delegate: KenzoDockStatusObserverDelegate? {
+
+ didSet {
+ delegate?.didChangeState(dock: dock)
+ }
+ }
+
+ init(dock: KenzoDock) {
+
+ self.dock = dock
+
+ observation = dock.observe(\KenzoDock.state) { _, _ in
+ self.delegate?.didChangeState(dock: self.dock)
+ }
+ }
}
final class KenzoDockStatus: NSObject {
- private let number: Int
- private let controller = NSArrayController()
- private var isTasking = false
- private var didNotify = false
- private var realTime: TimeInterval = 0.0 {
+ private enum DockState: Int {
+
+ case empty = 0
+ case hasShip = 2
+ case completed = 3
+ case notOpen = -1
- didSet { time = realTime as NSNumber }
+ case unknown = 999999
}
- @objc dynamic var time: NSNumber?
- @objc dynamic var state: NSNumber? {
+ static func valid(number: Int) -> Bool {
- didSet { updateState() }
+ return 1...4 ~= number
}
- @objc dynamic var completeTime: NSNumber?
+ let number: Int
+ private let observer: KenzoDockObserver
+
+ private(set) var time: TimeInterval?
+
+ private var isTasking = false
+
+ private var state: DockState = .unknown
+ private var rawState: Int = 0 {
+
+ didSet {
+ state = DockState(rawValue: rawState) ?? .unknown
+ }
+ }
+ private var completeTime: Int = 0
+
+ private var didNotify = false
+
+ weak var delegate: KenzoDockStatusObserver?
+
+ /// CAUTION: 初回起動時/マスタ更新時にはデータがないので失敗する
init?(number: Int) {
- guard case 1...4 = number else { return nil }
+ guard KenzoDockStatus.valid(number: number) else { return nil }
self.number = number
- super.init()
-
- controller.managedObjectContext = ServerDataStore.default.context
- controller.entityName = KenzoDock.entityName
- controller.fetchPredicate = NSPredicate(#keyPath(KenzoDock.id), equal: number)
- controller.automaticallyRearrangesObjects = true
- controller.fetch(nil)
+ guard let dock = ServerDataStore.default.kenzoDock(by: number) else { return nil }
+ self.observer = KenzoDockObserver(dock: dock)
- bind(NSBindingName(#keyPath(state)), to: controller, withKeyPath: "selection.state")
- bind(NSBindingName(#keyPath(completeTime)), to: controller, withKeyPath: "selection.complete_time")
+ super.init()
+
+ observer.delegate = self
}
private func updateState() {
- guard let state = state as? Int,
- let stat = DockState(rawValue: state) else {
-
- return Logger.shared.log("unknown State")
- }
-
- switch stat {
+ switch state {
+
case .empty, .notOpen:
isTasking = false
didNotify = false
+ time = nil
case .hasShip, .completed:
isTasking = true
+
+ case .unknown:
+ Logger.shared.log("unknown State")
}
+
+ delegate?.didUpdate(state: self)
}
+}
+
+extension KenzoDockStatus: DockInformationUpdater {
func update() {
- if !isTasking {
-
- time = nil
- return
- }
- guard let completeTime = completeTime as? Int else {
-
- time = nil
- return
+ defer {
+ delegate?.didUpdate(state: self)
}
+ guard isTasking else { return }
+
let compTime = TimeInterval(Int(completeTime / 1_000))
let diff = compTime - Date().timeIntervalSince1970
- realTime = max(0, diff)
+ // set to 0. if diff is less than 0.
+ time = max(0, diff)
+ // notify UserNotification.
if didNotify { return }
if diff > 0 { return }
}
}
+
+extension KenzoDockStatus: KenzoDockStatusObserverDelegate {
+
+ func didChangeState(dock: KenzoDock) {
+
+ rawState = dock.state
+ completeTime = dock.complete_time
+
+ updateState()
+ }
+}