// // SelectorGroupHandlerable.swift // VDS // // Created by Matt Bruce on 8/23/22. // import Foundation import UIKit ///MARK: Groups that allow anything selected public protocol SelectorGroupModelHandlerable: ModelHandlerable, Disabling, Surfaceable where ModelType: SelectorGroupModelable { associatedtype ModelHandlerType: ModelHandlerable where ModelType.SelectorModelType == ModelHandlerType.ModelType, ModelHandlerType: UIControl var selectorViews: [ModelHandlerType] { get set } func createModelHandler(selector: ModelHandlerType.ModelType) -> ModelHandlerType } extension SelectorGroupModelHandlerable { public func findSelectorView(id: UUID) -> ModelHandlerType? { return selectorViews.first(where: { existingSelectorView in return existingSelectorView.model.id == id }) } public func createModelHandler(selector: ModelHandlerType.ModelType) -> ModelHandlerType { //create view let newSelectorView = ModelHandlerType(with: selector) //add model update to the subscribers newSelectorView.handlerPublisher() .sink { [weak self] model in if let cached = self?.getCachedSelector(viewModel: model), newSelectorView.shouldUpdateView(viewModel: cached) { self?.replace(viewModel: model) } } .store(in: &subscribers) return newSelectorView } public func updateSelectors(){ let selectors = model.selectors.compactMap { existing in return existing.copyWith { $0.disabled = disabled $0.surface = surface } } model.selectors = selectors } public func getCachedSelector(viewModel: ModelHandlerType.ModelType) -> ModelHandlerType.ModelType? { if let index = model.selectors.firstIndex(where: { element in return element.id == viewModel.id }) { return model.selectors[index] } else { return nil } } public func replace(viewModel: ModelHandlerType.ModelType){ if let index = model.selectors.firstIndex(where: { element in return element.id == viewModel.id }) { model.selectors[index] = viewModel } } } ///MARK: Groups that allow single selections public protocol SelectorGroupSelectedModelHandlerable: SelectorGroupModelHandlerable { var selectedModel: ModelHandlerType.ModelType? { get set } func didSelect(selector: ModelHandlerType.ModelType) } extension SelectorGroupSelectedModelHandlerable { public func createModelHandler(selector: ModelHandlerType.ModelType) -> ModelHandlerType { //create view let newSelectorView = ModelHandlerType(with: selector) //add the selectedPublisher for the change newSelectorView.publisher(for: .valueChanged) .sink(receiveValue: { [weak self] control in guard self?.model.selectors.count ?? 0 > 0 else { return } self?.didSelect(selector: control.model) }) .store(in: &subscribers) //add model update to the subscribers newSelectorView.handlerPublisher() .sink { [weak self] model in if let cached = self?.getCachedSelector(viewModel: model), newSelectorView.shouldUpdateView(viewModel: cached) { self?.replace(viewModel: model) } } .store(in: &subscribers) return newSelectorView } public func didSelect(selector: ModelHandlerType.ModelType) { if var oldSelectedModel = selectedModel { oldSelectedModel.selected = false replace(viewModel: oldSelectedModel) } //only select is selected if selector.selected { var newSelectedModel = selector newSelectedModel.selected = true replace(viewModel: newSelectedModel) selectedModel = newSelectedModel } else { //ensure current value is removed selectedModel = nil } } }