added iOS source code
[wl-app.git] / iOS / WolneLektury / Model / BookDetailsModel.swift
1 //
2 //  BookDetailsModel.swift
3 //  WolneLektury
4 //
5 //  Created by Pawel Dabrowski on 30/05/2018.
6 //  Copyright © 2018 Fundacja Nowoczesna Polska. All rights reserved.
7 //
8
9 import UIKit
10 import RealmSwift
11
12 protocol BookBase {
13     var simple_thumb: String { get set }
14     var title: String { get set }
15     
16     func getAuthor() -> String
17 }
18
19 extension BookBase{
20     
21     // returns image url
22     func getCoverThumbUrl() -> URL?{
23         
24         if simple_thumb.count > 0{
25             var str = simple_thumb
26             
27             if (!str.contains(Config.MEDIA_URL) && !str.contains(Config.MEDIA_URL_HTTPS)) {
28                 str = Config.MEDIA_URL + str
29             }
30             
31             return str.getUrl()
32         }
33         return nil
34     }
35     
36     func getAttributedAuthorAndTitle(titleFont: UIFont, descFont: UIFont) -> NSAttributedString{
37         let titleAttributedText = NSMutableAttributedString(attributedString: NSAttributedString(string: getAuthor() + "\n", font: titleFont))
38         titleAttributedText.append(NSAttributedString(string: title, font: descFont))
39         return titleAttributedText
40     }
41 }
42
43 class BookDetailsModel: Object, BookBase, Decodable, NSCopying {
44     @objc dynamic var title: String = ""
45     @objc dynamic var simple_thumb: String = ""
46     
47     var genres = List<CategoryModel>()
48     var kinds = List<CategoryModel>()
49     @objc dynamic var url: String = ""
50     var media = List<MediaModel>()
51     @objc dynamic var simple_cover: String = ""
52     var epochs = List<CategoryModel>()
53     var authors = List<CategoryModel>()
54     @objc dynamic var pdf: String = ""
55     @objc dynamic var epub: String = ""
56     @objc dynamic var fragmentTitle = ""
57     @objc dynamic var fragmentHtml = ""
58     
59     @objc dynamic var audio_length: String = ""
60     @objc dynamic var cover_color: String = ""
61
62     //additional
63     @objc dynamic var currentChapter = 0
64     @objc dynamic var totalChapters = 0
65     @objc dynamic var currentAudioChapter = 0
66     @objc dynamic var totalAudioChapters = 0
67     @objc dynamic var slug = ""
68     
69     private var privateBgColor: UIColor?
70     var bgColor: UIColor{
71         get {
72             if let privateBgColor = privateBgColor {
73                 return privateBgColor
74             }
75             privateBgColor = UIColor(hex: cover_color)
76             return privateBgColor!
77         }
78         set {
79             privateBgColor = newValue
80         }
81     }
82     
83     override class func primaryKey() -> String? {
84         return "slug"
85     }
86
87     private enum BookDetailsModelCodingKeys: String, CodingKey {
88         case title
89         case simple_thumb
90         case genres
91         case kinds
92         case url
93         case media
94         case simple_cover
95         case epochs
96         case authors
97         case pdf
98         case epub
99         case fragment_data
100         case audio_length
101         case cover_color
102     }
103
104     convenience init(title: String, simple_thumb: String, url: String, simple_cover: String, pdf: String, epub: String, audio_length: String, cover_color: String, genres: [CategoryModel], kinds: [CategoryModel], media: [MediaModel], epochs: [CategoryModel], authors: [CategoryModel], fragmentTitle: String, fragmentHtml: String, slug: String) {
105         
106         self.init()
107         self.title = title
108         self.simple_thumb = simple_thumb
109         self.url = url
110         self.simple_cover = simple_cover
111         self.pdf = pdf
112         self.epub = epub
113         self.audio_length = audio_length
114         self.cover_color = cover_color
115         self.fragmentHtml = fragmentHtml
116         self.fragmentTitle = fragmentTitle
117         self.slug = slug
118         
119         self.genres = List<CategoryModel>()
120         self.kinds = List<CategoryModel>()
121         self.epochs = List<CategoryModel>()
122         self.authors = List<CategoryModel>()
123         self.media = List<MediaModel>()
124         
125         self.genres.append(objectsIn: genres)
126         self.kinds.append(objectsIn: kinds)
127         self.epochs.append(objectsIn: epochs)
128         self.authors.append(objectsIn: authors)
129         self.media.append(objectsIn: media)
130     }
131
132     convenience required init(from decoder: Decoder) throws {
133         let container = try decoder.container(keyedBy: BookDetailsModelCodingKeys.self)
134         
135         let title = try container.decode(String.self, forKey: .title)
136         let simple_thumb = try container.decode(String.self, forKey: .simple_thumb)
137         let url = try container.decode(String.self, forKey: .url)
138         let simple_cover = try container.decode(String.self, forKey: .simple_cover)
139         let pdf = try container.decode(String.self, forKey: .pdf)
140         let epub = try container.decode(String.self, forKey: .epub)
141         let audio_length = try container.decode(String.self, forKey: .audio_length)
142         let cover_color = try container.decode(String.self, forKey: .cover_color)
143
144         let genres = try container.decodeIfPresent([CategoryModel].self, forKey: .genres)
145         let kinds = try container.decodeIfPresent([CategoryModel].self, forKey: .kinds)
146         let epochs = try container.decodeIfPresent([CategoryModel].self, forKey: .epochs)
147         let authors = try container.decodeIfPresent([CategoryModel].self, forKey: .authors)
148         let media = try container.decodeIfPresent([MediaModel].self, forKey: .media)
149         
150         let fragment_data = try container.decodeIfPresent(FragmentModel.self, forKey: .fragment_data)
151         
152         let genresArray = genres ?? []
153         let kindsArray = kinds ?? []
154         let mediaArray = media ?? []
155         let epochsArray = epochs ?? []
156         let authorsArray = authors ?? []
157         
158         self.init(title: title, simple_thumb: simple_thumb, url: url, simple_cover: simple_cover, pdf: pdf, epub: epub, audio_length: audio_length, cover_color: cover_color, genres: genresArray, kinds: kindsArray, media: mediaArray, epochs: epochsArray, authors: authorsArray, fragmentTitle: fragment_data?.title ?? "", fragmentHtml: fragment_data?.html ?? "", slug: "")
159     }
160     
161     
162     func getAuthor() -> String {
163         return authors.map({$0.name}).joined(separator: ", ")
164     }
165     
166     func getGenres() -> String {
167         return genres.map({$0.name}).joined(separator: ", ")
168     }
169     
170     func getKinds() -> String {
171         return kinds.map({$0.name}).joined(separator: ", ")
172     }
173     
174     func getEpochs() -> String {
175         return epochs.map({$0.name}).joined(separator: ", ")
176     }
177     
178     func getAudiobookMediaModels() -> [MediaModel] {
179         var mediaModels = [MediaModel]()
180         
181         for mediaFile in media {
182             if mediaFile.type == "mp3" {
183                 mediaModels.append(mediaFile)
184             }
185         }
186         return mediaModels;
187     }
188     
189     func getAudiobookFilesUrls() -> [String] {
190         
191         return getAudiobookMediaModels().map({$0.url})
192     }
193     
194     func checkIfAllAudiobookFilesAreDownloaded() -> Bool{
195         
196         guard slug.count > 0 else {return false}
197         let audiobookUrls = getAudiobookFilesUrls()
198         
199         for url in audiobookUrls{
200             if !NSObject.audiobookExists(audioBookUrlString: url, bookSlug: slug) {
201                 return false
202             }
203         }
204         return true
205     }
206     
207     func copy(with zone: NSZone? = nil) -> Any {
208         
209         var genresArray = [CategoryModel]()
210         var kindsArray = [CategoryModel]()
211         var epochsArray = [CategoryModel]()
212         var authorsArray = [CategoryModel]()
213         var mediaArray = [MediaModel]()
214         
215         for object in genres{
216             genresArray.append(object.copy() as! CategoryModel)
217         }
218         
219         for object in kinds{
220             kindsArray.append(object.copy() as! CategoryModel)
221         }
222
223         for object in epochs{
224             epochsArray.append(object.copy() as! CategoryModel)
225         }
226         
227         for object in authors{
228             authorsArray.append(object.copy() as! CategoryModel)
229         }
230         
231         for object in media{
232             mediaArray.append(object.copy() as! MediaModel)
233         }
234         
235         let model = BookDetailsModel(title: title, simple_thumb: simple_thumb, url: url, simple_cover: simple_cover, pdf: pdf, epub: epub, audio_length: audio_length, cover_color: cover_color, genres: genresArray, kinds: kindsArray, media: mediaArray, epochs: epochsArray, authors: authorsArray, fragmentTitle: fragmentTitle, fragmentHtml: fragmentHtml, slug: slug)
236         if currentChapter > 0 {
237             model.currentChapter = currentChapter
238         }
239         if currentAudioChapter > 0 {
240             model.currentAudioChapter = currentAudioChapter
241         }
242         if totalAudioChapters > 0 {
243             model.totalAudioChapters = totalAudioChapters
244         }
245         if totalChapters > 0 {
246             model.totalAudioChapters = totalAudioChapters
247         }
248         return model
249     }
250     
251     func setInitialAudiobookChaptersValuesIfNeeded() {
252         if totalAudioChapters == 0 && currentAudioChapter == 0 {
253             DatabaseManager.shared.updateCurrentChapters(bookDetailsModel: self, currentChapter: nil, totalChapters: nil, currentAudioChapter: 0, totalAudioChapters: getAudiobookFilesUrls().count)
254         }
255     }
256 }