// // VehicleService.swift // AutoCatCore // // Created by Selim Mustafaev on 19.01.2025. // Copyright © 2025 Selim Mustafaev. All rights reserved. // import Foundation public typealias VehicleWithErrors = ( vehicle: VehicleDto, errors: [Error] ) public final class VehicleService { let apiService: ApiServiceProtocol let storageService: StorageServiceProtocol let locationService: LocationServiceProtocol public init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol, locationService: LocationServiceProtocol) { self.apiService = apiService self.storageService = storageService self.locationService = locationService } } extension VehicleService: VehicleServiceProtocol { func check( number: String, forceUpdate: Bool, trackLocation: Bool, additionalEvents: [VehicleEventDto], dbUpdatePolicy: DbUpdatePolicy ) async throws -> VehicleWithErrors { var vehicle = (try? await storageService.loadVehicle(number: number)) ?? VehicleDto(number: number) var errors: [Error] = [] // TODO: Check if additionalEvents already was added earlier (avoid duplication) let events = vehicle.events + additionalEvents let notes = vehicle.notes if !additionalEvents.isEmpty { vehicle.events = events vehicle.updatedDate = Date().timeIntervalSince1970 vehicle.synchronized = false } async let locationTask = trackLocation ? locationService.getRecentLocation() : nil async let vehicleTask = apiService.checkVehicle(by: number, notes: notes, events: events, force: forceUpdate) do { vehicle = try await vehicleTask } catch { errors.append(error) } if trackLocation { do { if let event = try await locationTask { vehicle.events.append(event) vehicle.updatedDate = Date().timeIntervalSince1970 vehicle.synchronized = false if !vehicle.unrecognized { vehicle = try await apiService.add(event: event, to: number) } } } catch { errors.append(error) } } await locationService.resetLastEvent() try await storageService.updateVehicle(dto: vehicle, policy: dbUpdatePolicy) return VehicleWithErrors(vehicle: vehicle, errors: errors) } public func check(number: String) async throws -> VehicleWithErrors { #if targetEnvironment(macCatalyst) try await check( number: number, forceUpdate: false, trackLocation: false, additionalEvents: [], dbUpdatePolicy: .always ) #else try await check( number: number, forceUpdate: false, trackLocation: true, additionalEvents: [], dbUpdatePolicy: .always ) #endif } public func updateHistory(number: String) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: true, trackLocation: false, additionalEvents: [], dbUpdatePolicy: .always ) } public func updateSearch(number: String) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: true, trackLocation: false, additionalEvents: [], dbUpdatePolicy: .ifExists ) } public func checkRecord(number: String, event: VehicleEventDto?) async throws -> VehicleWithErrors { try await check( number: number, forceUpdate: false, trackLocation: false, additionalEvents: event.flatMap { [$0] } ?? [], dbUpdatePolicy: .always ) } }