AutoCat/AutoCat/Models/Vehicle.swift

339 lines
11 KiB
Swift

import Foundation
import RealmSwift
import DifferenceKit
class VehicleName: Object, Decodable, Cloneable {
@objc dynamic var original: String?
@objc dynamic var normalized: String?
required init(copy: VehicleName) {
self.original = copy.original
self.normalized = copy.normalized
}
required init() {
}
}
class VehicleBrand: Object, Decodable, Cloneable {
@objc dynamic var name: VehicleName?
@objc dynamic var logo: String?
required init(copy: VehicleBrand) {
self.name = copy.name?.clone()
self.logo = copy.logo
}
required init() {
super.init()
}
}
class VehicleModel: Object, Decodable, Cloneable {
@objc dynamic var name: VehicleName?
required init(copy: VehicleModel) {
self.name = copy.name?.clone()
}
required init() {
super.init()
}
}
class VehicleEngine: Object, Decodable, Cloneable {
@objc dynamic var number: String?
var volume: RealmOptional<Int> = RealmOptional(0)
@objc dynamic var powerHp: Float = 0
var powerKw: RealmOptional<Float> = RealmOptional(0)
@objc dynamic var fuelType: String?
enum CodingKeys: String, CodingKey {
case number, volume, powerHp, powerKw, fuelType
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.number = try container.decodeIfPresent(String.self, forKey: .number)
self.volume = RealmOptional(try container.decodeIfPresent(Int.self, forKey: .volume))
self.powerHp = try container.decode(Float.self, forKey: .powerHp)
self.powerKw = RealmOptional(try container.decodeIfPresent(Float.self, forKey: .powerKw))
self.fuelType = try container.decodeIfPresent(String.self, forKey: .fuelType)
}
required init() {
super.init()
}
required init(copy: VehicleEngine) {
self.number = copy.number
self.volume = copy.volume
self.powerHp = copy.powerHp
self.powerKw = copy.powerKw
self.fuelType = copy.fuelType
}
}
class VehiclePhoto: Object, Decodable, Cloneable {
@objc dynamic var brand: String?
@objc dynamic var model: String?
@objc dynamic var date: TimeInterval = 0
@objc dynamic var url: String = ""
override var description: String {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier:"GMT")
formatter.dateStyle = .medium
formatter.timeStyle = .none
let date = Date(timeIntervalSince1970: self.date/1000)
let dateStr = formatter.string(from: date)
return "\(self.brand ?? "") \(self.model ?? "") (\(dateStr))"
}
required init(copy: VehiclePhoto) {
self.brand = copy.brand
self.model = copy.model
self.date = copy.date
self.url = copy.url
}
required init() {
super.init()
}
}
enum OwnerType: String, CustomStringConvertible {
case legal
case individual
var description: String {
switch self {
case .legal: return NSLocalizedString("legal", comment: "Owner type")
case .individual: return NSLocalizedString("individual", comment: "Owner type")
}
}
}
enum SteeringWheelPosition: CustomStringConvertible {
case left
case right
case unknown
var description: String {
switch self {
case .left: return "Left"
case .right: return "Right"
case .unknown: return "Unknown"
}
}
}
class VehicleOwnershipPeriod: Object, Decodable, Cloneable {
@objc dynamic var lastOperation: String = ""
@objc dynamic var ownerType: String = ""
@objc dynamic var from: Int64 = 0
@objc dynamic var to: Int64 = 0
@objc dynamic var region: String?
@objc dynamic var registrationRegion: String?
@objc dynamic var locality: String?
@objc dynamic var code: String?
@objc dynamic var street: String?
@objc dynamic var building: String?
@objc dynamic var inn: String?
required init(copy: VehicleOwnershipPeriod) {
self.lastOperation = copy.lastOperation
self.ownerType = copy.ownerType
self.from = copy.from
self.to = copy.to
self.region = copy.region
self.registrationRegion = copy.registrationRegion
self.locality = copy.locality
self.code = copy.code
self.street = copy.street
self.building = copy.building
self.inn = copy.inn
}
required init() {
super.init()
}
}
class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
@objc dynamic var brand: VehicleBrand?
@objc dynamic var model: VehicleModel?
@objc dynamic var color: String?
@objc dynamic var year: Int = 0
@objc dynamic var category: String?
@objc dynamic var engine: VehicleEngine?
@objc private dynamic var number: String = ""
@objc dynamic var currentNumber: String?
@objc dynamic var vin1: String?
@objc dynamic var vin2: String?
@objc dynamic var sts: String?
@objc dynamic var pts: String?
var isRightWheel = RealmOptional<Bool>()
var isJapanese: RealmOptional<Bool> = RealmOptional<Bool>()
@objc dynamic var addedDate: TimeInterval = 0
@objc dynamic var updatedDate: TimeInterval = 0
@objc dynamic var addedBy: String = ""
var photos = List<VehiclePhoto>()
var ownershipPeriods = List<VehicleOwnershipPeriod>()
var events = List<VehicleEvent>()
var osagoContracts = List<Osago>()
var ads = List<VehicleAd>()
var differenceIdentifier: String { self.number }
func isContentEqual(to source: Vehicle) -> Bool {
return self == source
}
enum CodingKeys: String, CodingKey {
case brand
case model
case color
case year
case category
case engine
case number
case currentNumber
case vin1
case vin2
case sts
case pts
case isRightWheel
case isJapanese
case addedDate
case addedBy
case photos
case ownershipPeriods
case events
case osagoContracts
case ads
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.brand = try container.decodeIfPresent(VehicleBrand.self, forKey: .brand)
self.model = try container.decodeIfPresent(VehicleModel.self, forKey: .model)
self.color = try container.decodeIfPresent(String.self, forKey: .color)
self.year = try container.decodeIfPresent(Int.self, forKey: .year) ?? 0
self.category = try container.decodeIfPresent(String.self, forKey: .category)
self.number = try container.decode(String.self, forKey: .number)
self.engine = try container.decodeIfPresent(VehicleEngine.self, forKey: .engine)
self.currentNumber = try container.decodeIfPresent(String.self, forKey: .currentNumber)
self.vin1 = try container.decodeIfPresent(String.self, forKey: .vin1)
self.vin2 = try container.decodeIfPresent(String.self, forKey: .vin2)
self.sts = try container.decodeIfPresent(String.self, forKey: .sts)
self.pts = try container.decodeIfPresent(String.self, forKey: .pts)
self.isRightWheel = RealmOptional(try container.decodeIfPresent(Bool.self, forKey: .isRightWheel))
self.isJapanese = RealmOptional(try container.decodeIfPresent(Bool.self, forKey: .isJapanese))
self.addedDate = (try container.decode(TimeInterval.self, forKey: .addedDate))/1000
self.addedBy = try container.decode(String.self, forKey: .addedBy)
if let photosArray = try container.decodeIfPresent([VehiclePhoto].self, forKey: .photos) {
self.photos.append(objectsIn: photosArray)
}
if let ownersipsArray = try container.decodeIfPresent([VehicleOwnershipPeriod].self, forKey: .ownershipPeriods) {
self.ownershipPeriods.append(objectsIn: ownersipsArray)
}
if let eventsArray = try container.decodeIfPresent([VehicleEvent].self, forKey: .events) {
self.events.append(objectsIn: eventsArray)
}
if let lastEventDate = self.events.max(by: { $0.date < $1.date })?.date {
self.updatedDate = max(self.addedDate, lastEventDate)
} else {
self.updatedDate = self.addedDate
}
if let osago = try container.decodeIfPresent([Osago].self, forKey: .osagoContracts) {
self.osagoContracts.append(objectsIn: osago)
}
if let ads = try container.decodeIfPresent([VehicleAd].self, forKey: .ads) {
self.ads.append(objectsIn: ads)
}
}
required init() {
super.init()
}
init(_ number: String) {
self.number = number
self.addedDate = Date().timeIntervalSince1970
self.updatedDate = self.addedDate
}
func getNumber() -> String {
return self.number
}
override static func primaryKey() -> String? {
return "number"
}
override class func ignoredProperties() -> [String] {
return ["id", "identifier", "differenceIdentifier"]
}
var unrecognized: Bool {
return self.brand == nil
}
var outdated: Bool {
if let current = self.currentNumber {
return current != self.number
} else {
return false
}
}
// MARK: - Cloneable
required init(copy: Vehicle) {
self.brand = copy.brand
self.model = copy.model
self.color = copy.color
self.year = copy.year
self.category = copy.category
self.engine = copy.engine
self.number = copy.number
self.currentNumber = copy.currentNumber
self.vin1 = copy.vin1
self.vin2 = copy.vin2
self.sts = copy.sts
self.pts = copy.pts
self.isRightWheel = copy.isRightWheel
self.isJapanese = copy.isJapanese
self.addedDate = copy.addedDate
self.addedBy = copy.addedBy
self.updatedDate = copy.updatedDate
let photos = List<VehiclePhoto>()
photos.append(objectsIn: copy.photos.map { $0.clone() })
self.photos = photos
let ownerships = List<VehicleOwnershipPeriod>()
ownerships.append(objectsIn: copy.ownershipPeriods.map { $0.clone() })
self.ownershipPeriods = ownerships
let events = List<VehicleEvent>()
events.append(objectsIn: copy.events.map { $0.clone() })
self.events = events
let osago = List<Osago>()
osago.append(objectsIn: copy.osagoContracts.map { $0.clone() })
self.osagoContracts = osago
let ads = List<VehicleAd>()
ads.append(objectsIn: copy.ads.map { $0.clone() })
self.ads = ads
}
}