OSDN Git Service

Sequenceのextensionを分離
[kcd/KCD.git] / KCD / KenzoDockStatus.swift
1 //
2 //  KenzoDockStatus.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/22.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 protocol KenzoDockStatusObserver: class {
12     
13     func didUpdate(state: KenzoDockStatus)
14 }
15
16 protocol KenzoDockStatusObserverDelegate: class {
17     
18     func didChangeState(dock: KenzoDock)
19 }
20
21 final class KenzoDockObserver {
22     
23     private let dock: KenzoDock
24     private var observation: NSKeyValueObservation?
25     
26     weak var delegate: KenzoDockStatusObserverDelegate? {
27         
28         didSet {
29             
30             delegate?.didChangeState(dock: dock)
31         }
32     }
33     
34     init(dock: KenzoDock) {
35         
36         self.dock = dock
37         
38         observation = dock.observe(\KenzoDock.state) { _, _ in
39             
40             self.delegate?.didChangeState(dock: self.dock)
41         }
42     }
43 }
44
45 final class KenzoDockStatus: NSObject {
46     
47     private enum DockState: Int {
48         
49         case empty = 0
50         
51         case hasShip = 2
52         
53         case completed = 3
54         
55         case notOpen = -1
56         
57         case unknown = 999999
58     }
59     
60     static func valid(number: Int) -> Bool {
61         
62         return 1...4 ~= number
63     }
64     
65     let number: Int
66     private let observer: KenzoDockObserver
67     
68     private(set) var time: TimeInterval?
69     
70     private var isTasking = false
71     
72     private var state: DockState = .unknown
73     private var rawState: Int = 0 {
74         
75         didSet {
76             
77             state = DockState(rawValue: rawState) ?? .unknown
78         }
79     }
80     private var completeTime: Int = 0
81     
82     private var didNotify = false
83     
84     weak var delegate: KenzoDockStatusObserver?
85     
86     /// CAUTION: 初回起動時/マスタ更新時にはデータがないので失敗する
87     init?(number: Int) {
88         
89         guard KenzoDockStatus.valid(number: number) else {
90             
91             return nil
92         }
93         
94         self.number = number
95         
96         guard let dock = ServerDataStore.default.kenzoDock(by: number) else {
97             
98             return nil
99         }
100         
101         self.observer = KenzoDockObserver(dock: dock)
102         
103         super.init()
104                 
105         observer.delegate = self
106     }
107     
108     private func updateState() {
109         
110         switch state {
111             
112         case .empty, .notOpen:
113             isTasking = false
114             didNotify = false
115             time = nil
116             
117         case .hasShip, .completed:
118             isTasking = true
119             
120         case .unknown:
121             Logger.shared.log("unknown State")
122             
123         }
124         
125         delegate?.didUpdate(state: self)
126     }
127 }
128
129 extension KenzoDockStatus: DockInformationUpdater {
130     
131     func update() {
132         
133         defer {
134             
135             delegate?.didUpdate(state: self)
136         }
137         
138         guard isTasking else {
139             
140             return
141         }
142         
143         let compTime = TimeInterval(Int(completeTime / 1_000))
144         let diff = compTime - Date().timeIntervalSince1970
145         
146         // set to 0. if diff is less than 0.
147         time = max(0, diff)
148         
149         // notify UserNotification.
150         if didNotify {
151             
152             return
153         }
154         if diff > 0 {
155             
156             return
157         }
158         
159         let notification = NSUserNotification()
160         let format = LocalizedStrings.buildingWillFinish.string
161         notification.title = String(format: format, number as NSNumber)
162         notification.informativeText = notification.title
163         
164         if UserDefaults.standard[.playFinishKenzoSound] {
165             
166             notification.soundName = NSUserNotificationDefaultSoundName
167         }
168         
169         NSUserNotificationCenter.default.deliver(notification)
170         
171         didNotify = true
172     }
173     
174 }
175
176 extension KenzoDockStatus: KenzoDockStatusObserverDelegate {
177     
178     func didChangeState(dock: KenzoDock) {
179         
180         rawState = dock.state
181         completeTime = dock.complete_time
182         
183         updateState()
184     }
185 }