OSDN Git Service

swiftlint 'line_length'の警告を修正
[kcd/KCD.git] / KCD / StrengthenListViewController.swift
1 //
2 //  StrengthenListViewController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/25.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 fileprivate let resourceName = "EnhancementListItem2"
12 fileprivate let resourceExtension = "plist"
13
14 class StrengthenListViewController: MainTabVIewItemViewController {
15     private let notifier = PeriodicNotifier(hour: 0, minutes: 0)
16     private let plistDownloadNotifier = PeriodicNotifier(hour: 23, minutes: 55)
17         
18     @IBOutlet weak var tableView: NSTableView!
19     
20     dynamic var itemList: [EnhancementListItem] = []
21     dynamic var offsetDay: Int = 0 {
22         didSet { buildList() }
23     }
24     override var nibName: String! {
25         return "StrengthenListViewController"
26     }
27     private let downloader = EnhancementListItemDownloader()
28     private var equipmentStrengthenList: [EnhancementListItem] = []
29     
30     override func viewDidLoad() {
31         super.viewDidLoad()
32         
33         if let url = Bundle.main.url(forResource: resourceName, withExtension: resourceExtension),
34             let data = try? Data(contentsOf: url) {
35             guard let array = NSKeyedUnarchiver.unarchiveObject(with: data) as? [EnhancementListItem]
36                 else {
37                     print("\(resourceName).\(resourceExtension) not found.")
38                     return
39             }
40             equipmentStrengthenList = array
41             buildList()
42             
43             #if DEBUG
44 //                downloadPList()
45             #else
46                 downloadPList()
47             #endif
48         }
49         
50         let nc = NotificationCenter.default
51         nc.addObserver(forName: .Periodic, object: notifier, queue: nil) { [weak self] _ in
52             guard let `self` = self else { return }
53             self.buildList()
54         }
55         nc.addObserver(forName: .Periodic, object: plistDownloadNotifier, queue: nil) { [weak self] _ in
56             guard let `self` = self else { return }
57             self.downloadPList()
58         }
59     }
60     private func buildList() {
61         var newList: [EnhancementListItem] = {
62             if offsetDay == -1 { return allItemList() }
63             
64             let currentDay = NSCalendar.current.dateComponents([.weekday], from: Date())
65             var targetWeekday = currentDay.weekday! + offsetDay
66             if targetWeekday > 7 { targetWeekday = 1 }
67             return equipmentStrengthenList.filter { $0.weekday == targetWeekday }
68         }()
69         
70         var type: EquipmentType = .unknown
71         let group: [(EquipmentType, Int)] = newList.enumerated().flatMap {
72             if type != $0.element.equipmentType {
73                 type = $0.element.equipmentType
74                 return (type, $0.offset)
75             }
76             return nil
77         }
78         let t = SlotItemEquipTypeTransformer()
79         let prototype = newList[0]
80         group.reversed().forEach {
81             let item = prototype.replace(identifier: t.transformedValue($0.0.rawValue) as? String,
82                                          equipmentType: .unknown)
83             newList.insert(item, at: $0.1)
84         }
85         itemList = newList
86     }
87     private func downloadPList() {
88         downloader.download { [weak self] (array) in
89             guard let `self` = self else { return }
90             DispatchQueue.main.async {
91                 self.equipmentStrengthenList = array
92                 self.buildList()
93             }
94         }
95     }
96     private func allItemList() -> [EnhancementListItem] {
97         var allIdentifier: [String] = []
98         var dict: [String: EnhancementListItem] = [:]
99         equipmentStrengthenList.forEach {
100             var item = dict[$0.identifier]
101             if item == nil {
102                 item = $0.replace(weekday: 10)
103                 dict[$0.identifier] = item
104                 allIdentifier.append($0.identifier)
105             }
106             var secondShips = item?.secondsShipNames
107             secondShips?.append(contentsOf: $0.secondsShipNames)
108             secondShips?.uniqueInPlace()
109             dict[$0.identifier] = item?.replace(secondsShipNames: secondShips)
110         }
111         
112         return allIdentifier.flatMap { dict[$0] }
113     }
114 }
115
116 extension StrengthenListViewController: NSTableViewDelegate {
117     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
118         let item = itemList[row]
119         let identifier = (item.equipmentType == .unknown) ? "GroupCell" : "ItemCell"
120         return tableView.make(withIdentifier: identifier, owner: nil)
121     }
122     func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
123         return (itemList[row].equipmentType == .unknown)
124     }
125     func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
126         return (itemList[row].equipmentType == .unknown) ? 23.0 : 103.0
127     }
128 }
129
130 fileprivate class EnhancementListItemDownloader: NSObject, URLSessionDownloadDelegate {
131     override init() {
132         super.init()
133         
134         plistDownloadQueue = OperationQueue()
135         plistDownloadQueue.name = "StrengthenListViewControllerPlistDownloadQueue"
136         plistDownloadQueue.maxConcurrentOperationCount = 1
137         plistDownloadQueue.qualityOfService = .background
138         let configuration = URLSessionConfiguration.default
139         plistDownloadSession = URLSession(configuration: configuration,
140                                           delegate: self,
141                                           delegateQueue: plistDownloadQueue)
142     }
143     
144     private var plistDownloadSession: URLSession!
145     private var plistDownloadQueue: OperationQueue!
146     private var plistDownloadTask: URLSessionDownloadTask?
147     private var finishOperation: (([EnhancementListItem]) -> Void)?
148     
149     func download(using block: @escaping ([EnhancementListItem]) -> Void) {
150         if let _ = plistDownloadTask { return }
151         // swiftlint:disable:next line_length
152         guard let plistURL = URL(string: "http://git.osdn.jp/view?p=kcd/KCD.git;a=blob;f=KCD/\(resourceName).\(resourceExtension);hb=HEAD")
153             else { return }
154         
155         finishOperation = block
156         plistDownloadTask = plistDownloadSession.downloadTask(with: plistURL)
157         plistDownloadTask?.resume()
158     }
159     
160     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
161         plistDownloadTask = nil
162         guard let data = try? Data(contentsOf: location, options: []),
163             let list = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? [EnhancementListItem]
164             else { return }
165         finishOperation?(list)
166     }
167     func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
168         plistDownloadTask = nil
169     }
170 }