// // InsertCannulaViewModel.swift // OmniKit // // Created by Pete Schwamb on 3/10/20. // Copyright © 2021 LoopKit Authors. All rights reserved. // import LoopKit import LoopKitUI import OmniKit public protocol CannulaInserter { func insertCannula(completion: @escaping (Result) -> ()) func checkCannulaInsertionFinished(completion: @escaping (OmnipodPumpManagerError?) -> Void) } extension OmnipodPumpManager: CannulaInserter {} class InsertCannulaViewModel: ObservableObject, Identifiable { enum InsertCannulaViewModelState { case ready case startingInsertion case inserting(finishTime: CFTimeInterval) case checkingInsertion case error(OmnipodPumpManagerError) case finished var actionButtonAccessibilityLabel: String { switch self { case .ready, .startingInsertion: return LocalizedString("Insert Cannula", comment: "Insert cannula action button accessibility label while ready to pair") case .inserting: return LocalizedString("Inserting. Please wait.", comment: "Insert cannula action button accessibility label while pairing") case .checkingInsertion: return LocalizedString("Checking Insertion", comment: "Insert cannula action button accessibility label checking insertion") case .error(let error): return String(format: "%@ %@", error.errorDescription ?? "", error.recoverySuggestion ?? "") case .finished: return LocalizedString("Cannula inserted successfully. Continue.", comment: "Insert cannula action button accessibility label when cannula insertion succeeded") } } var instructionsDisabled: Bool { switch self { case .ready, .error: return false default: return true } } var nextActionButtonDescription: String { switch self { case .ready: return LocalizedString("Insert Cannula", comment: "Cannula insertion button text while ready to insert") case .error: return LocalizedString("Retry", comment: "Cannula insertion button text while showing error") case .inserting, .startingInsertion: return LocalizedString("Inserting...", comment: "Cannula insertion button text while inserting") case .checkingInsertion: return LocalizedString("Checking...", comment: "Cannula insertion button text while checking insertion") case .finished: return LocalizedString("Continue", comment: "Cannula insertion button text when inserted") } } var nextActionButtonStyle: ActionButton.ButtonType { switch self { case .error(let error): if !error.recoverable { return .destructive } default: break } return .primary } var progressState: ProgressIndicatorState { switch self { case .ready, .error: return .hidden case .startingInsertion, .checkingInsertion: return .indeterminantProgress case .inserting(let finishTime): return .timedProgress(finishTime: finishTime) case .finished: return .completed } } var showProgressDetail: Bool { switch self { case .ready: return false default: return true } } var isProcessing: Bool { switch self { case .startingInsertion, .inserting: return true default: return false } } var isFinished: Bool { if case .finished = self { return true } return false } } var error: OmnipodPumpManagerError? { if case .error(let error) = self.state { return error } return nil } @Published var state: InsertCannulaViewModelState = .ready var didFinish: (() -> Void)? var didRequestDeactivation: (() -> Void)? var cannulaInserter: CannulaInserter init(cannulaInserter: CannulaInserter) { self.cannulaInserter = cannulaInserter } // private func handleEvent(_ event: ActivationStep2Event) { // switch event { // case .insertingCannula: // let finishTime = TimeInterval(Pod.estimatedCannulaInsertionDuration) // state = .inserting(finishTime: CACurrentMediaTime() + finishTime) // case .step2Completed: // state = .finished // default: // break // } // } private func checkCannulaInsertionFinished() { state = .startingInsertion cannulaInserter.checkCannulaInsertionFinished() { (error) in DispatchQueue.main.async { if let error = error { self.state = .error(error) } else { self.state = .finished } } } } private func insertCannula() { state = .startingInsertion cannulaInserter.insertCannula { (result) in DispatchQueue.main.async { switch(result) { case .success(let finishTime): self.state = .inserting(finishTime: CACurrentMediaTime() + finishTime) let delay = finishTime if delay > 0 { DispatchQueue.main.asyncAfter(deadline: .now() + delay) { self.checkCannulaInsertionFinished() // now check if actually ready } } else { self.state = .finished } case .failure(let error): self.state = .error(error) } } // switch status { // case .error(let error): // self.state = .error(error) // case .event(let event): // self.handleEvent(event) // } } } public func continueButtonTapped() { switch state { case .finished: didFinish?() case .error(let error): if error.recoverable { insertCannula() } else { didRequestDeactivation?() } default: insertCannula() } } } public extension OmnipodPumpManagerError { var recoverable: Bool { //TODO return true // switch self { // case .podIsInAlarm: // return false // case .activationError(let activationErrorCode): // switch activationErrorCode { // case .podIsLumpOfCoal1Hour, .podIsLumpOfCoal2Hours: // return false // default: // return true // } // case .internalError(.incompatibleProductId): // return false // case .systemError: // return false // default: // return true // } } }